Parallélisme: Expérience sur un serveur de département

par Brigitte Watzke-Lerebours, DC-IGC EPFL
Comme la plupart de ceux qui tentent de modéliser des structures moléculaires, je me trouve confrontée au dilemme suivant: respecter simultanément deux critères a priori antinomiques: investigation scientifiquement la plus complète et temps de calcul minimal. Le premier critère est dans la mesure du possible rempli grâce à l'élaboration d'un programme Fortran sur mesure ou fait main (je devrais plutôt écrire fait mains, car la paternité du programme revient pour la plus grande part aux Professeurs G. Rutledge du MIT et U. Suter de lŒETHZ). En ce qui concerne le deuxième critère, il est apparu ingénieux d'essayer de paralléliser le code afin d'utiliser au mieux les ressources informatiques disponibles, tout en réduisant le temps de calcul.

La modélisation de structures semi-cristallines de polymères, donc la recherche de conformations d'énergie minimale implique une étape de calculs d'énergie après modifications systématiques (mais limitées à des régions de l'espace des paramètres ayant un sens physique) et simultanées de toutes les nombreuses variables concernées (pour exemple: valeurs des distances des liaisons chimiques, des angles, des angles de torsion, distances des chaînes polymériques les unes par rapport aux autres, orientations de ces chaînes, géométrie des cellules du réseau semi-cristallin...). Il va sans dire que cette phase de scan est l'étape du projet coûteuse en temps.

Afin de minimiser le temps de calcul, jŒai été intéressée par une optimisation de mon code, réalisée sur un exemple test sur des serveurs de département Silicon Graphics.

Détermination du profil d'exécution

En utilisant les outils dŒanalyse de performance on s'aperçoit que pratiquement 65% du temps total d'exécution est utilisé dans la routine se chargeant du calcul de l'énergie. Il est intéressant de voir si lŒon peut paralléliser cette routine. Toutefois la règle d'Amdahl montre que le gain réel dans ce cas n'est pas très grand. En effet avec un système, par exemple de 8 processeurs, on obtient:

65% /8 + 35% = 42%

L'exécution s'effectuera dans le meilleur des cas en un peu moins que la moitié du temps de la version scalaire. Pour la version avec 8 processeurs, le speedup n'est pas intéressant.

Essai de parallélisation au niveau supérieur

On aborde le problème au niveau du processus lui-même pour voir s'il est parallélisable. L'ensemble du processus effectue un scan sur un grand nombre de cellules pour chaque conformation de variable, et référence chaque cellule de façon indépendante. Il serait intéressant de paralléliser le code de telle façon que les cellules soient scannées en parallèle. Bien que l'idée paraisse simple, on se heurte à la difficulté suivante: l'ensemble des procédures impliquées dans le scan référence un ensemble de blocs COMMON et les modifie à chaque itération. On se trouve donc devant un problème de dépendance des données.

Solution

On peut envisager de copier l'ensemble des blocs COMMON avant la phase de scan et ceci pour l'ensemble des processeurs. Il reste à s'assurer que les variables locales à chaque scan de cellules soient rendues indépendantes pour les processeurs. Ceci peut être réalisé de façon très simple en incluant 2 pragmas (ou commentaires) de compilation dans la routine principale, soient:

C$COPYIN /common block/ qui recopie le common block donné à l'ensemble des processeurs.
C$DOACROSS LOCAL(liste de variable) qui demande au compilateur de générer du code en version parallèle en gardant les variables indiquées en copie locale à chaque processeur.

Le parallélisme du scan des cellules étant atteint, on a le choix entre deux stratégies:

C'est cette dernière variante qui a été retenue puisque le temps nécessaire pour scanner une cellule n'est pas le même d'une cellule à l'autre. Compilation et exécution Après compilation, l'exécution d'un test court donne les résultats suivants:

On obtient donc un speedup quasi-linéaire. LŒécart tient au fait qu'il y a une partie d'initialisation et d'écriture des résultats qui s'effectue en mode scalaire. De plus il existe un temps d'overhead causé par le démarrage des sections parallélisées.

Les résultats obtenus sur plusieurs échantillons ont montré la justesse des calculs. On peut donc s'attaquer à des problèmes réels. Conclusion Une fois l'effort de parallélisation effectué, il est possible d'exécuter le même code sans modification sur un nombre quelconque de processeurs ainsi que sur d'autres processeurs plus rapide du type TFP.

Cet exemple montre qu'il est possible de paralléliser un code existant sans devoir le réécrire et ceci à moindre frais de modifications. D'autre part le gain de temps obtenu se traduit immédiatement en gain de travail pour l'analyse de problèmes nécessitant autrement des mois de calculs.

Je remercie particulièrement pour leur aide Francis Lapique du SIC et Paride Zizzari, Silicon Graphics, tél.: 621 9273/9250, e-mail: paride@lausanne.sgi.com n


article paru dans le Flash informatique no 6 du 21 juin 1994