Environnement SGI Origin 2000
v 3.0

Guy Moebs
Guy.Moebs@crihan.fr

Plan de la formation
1. Environnement de travail
2. Outils d’aide au développement
3. Optimisation scalaire
4. Parallélisme

1- Environnement de travail
A. Présentation matérielle
B. Présentation logicielle
C. Arborescence
D. Soumission batch

1- A. Architecture matérielle O2000
Architecture O2000 (64 processeurs) :

1- A. Architecture matérielle O2000
Sommet du cube constitué :
un router
deux noeuds
Router connecté à 4 routers voisins
Noeud composé :
2 processeurs R10000
un commutateur HUB
une mémoire partagée (1 Go)

1- A. Architecture matérielle O2000
Le HUB :
est connecté aux deux processeurs du noeud,
sert d'interface entrées/sorties et et de connexion avec le reste des processeurs de la machine.
La mémoire :
est partagée entre les processeurs du noeud,
est adressable par l'ensemble des processeurs de la machine.

1- A. Architecture matérielle O2000
Processeurs type R10000 (MIPS IV) :
une fréquence horloge de 195 MHz,
une puissance crête/processeur de 390 Mflops,
un transfert crête de données vers le cache secondaire de 2.08 gbits/s,
deux espaces cache :
un cache primaire d'instructions de 32 Ko et de données de 32Ko,
un cache secondaire de 4 Mo.
Mémoire totale : 32 Go.

1- A. Architecture matérielle O2000
Organisation de la mémoire

1- A. Architecture matérielle O2000
Temps d’accès mémoire

1- A. Architecture matérielle O2000
Volume de stockage disque : 270 Go
Configuration avec robot d'archivage et de sauvegarde de marque ADIC-GRAU AML/S 1000
(Technologie DLT 7000)
Capacité de 10.5 Téra Octets
Accès à illiac8 via une interface ATM OC-3 (155Mbits/s)

1- B. Présentation logicielle
1. Compilateurs
2. Modules
3. Débogueurs - éditeurs - logiciels de graphisme
4. Bibliothèques scientifiques
5. Outils de développement
6. Parallélisation

1- B. Présentation logicielle  1. Compilateurs
Compilateurs SGI :
Fortran 77 : f77
Fortran 90 : f90
C : cc
C++ : CC
Adressage des données  :
-n32 ou -64 selon l’espace d’adressage (< ou > 2Go)
Compilateur HPF (Portland Group) :
HPF (High Performance Fortran) : pghpf
langage data parallel basé sur le F90

1- B. Présentation logicielle  2. Modules
Module MPT (Message Passing Toolkit) :
Environnement d’utilisation de MPI, SHMEM, PVM
=> chemins, variables d’environnement, librairies, exécutables
Installation statique      pour les versions >= 1.4
Installation par module pour les versions <= 1.3
=> commande « module » (module help) :
module avail : ensemble des modules présents
module list :    ensemble des modules déjà activés
module load mpt :      activation      du module mpt
module unload mpt : désactivation du module mpt

1- B. Présentation logicielle  3. Débogueurs
Débogueurs :
dbx,
cvd (outil SGI).
Éditeurs :
vi,
emacs,
xedit,
nedit.
Logiciels de graphisme :
xmgr,
gnuplot.

1- B. Présentation logicielle  4. Bibliothèques
Bibliothèque SCSL (optimisées par SGI) :
BLAS (portabilité complète),
LAPACK (portabilité complète),
FFT (portabilité restreinte !).
en INTEGER*4 : link avec –lscs ou -lscs_mp (version parallèle)
en INTEGER*8 : link avec –lscs_i8 ou –lscs_i8_mp (version parallèle)
Mathématique,
=> link avec -lfastm (au lieu de -lm par défaut)
Bibliothèques domaine public :
SCALAPACK,
=> link avec /local/SCALAPACK/libscalapack[64/n32].a
BLACS,
=> link avec /local/BLACS/libmpiblacs[64/n32].a

1- B. Présentation logicielle  5. Outils
Perfex : comptage d’évèments matériels
Speedshop :
ssrun : effectue les mesures,
prof : analyse des échantillonnages.
WorkShop :
Build Manager (cvbuild/cvmake) : aide à la compilation,
Static Analyser (cvstatic) : aide à l’analyse de programmes,
Debugger (cvd) : débogueur,
Performance Analyser (cvperf) : profilage de programmes,
Parallel Analyser (cvpav) : aide à la parallélisation.
Documentation :
manpage et insight

1- B. Présentation logicielle  6. Parallélisation
Parallélisme SMP (Shared Memory Processing) :
insertion de directives de compilation : OpenMP
Parallélisme MPP (Massively Parallel Processing) :
modules mpt : MPI, SHMEM, PVM
version constructeur
Parallélisme de données (data parallelism) :
HPF (Portland Group)

1- C. Arborescence
Compte informatique utilisateur :

1- C. Arborescence
Sauvegarde des $HOME_DIR toutes les nuits
Migration des $HOME_SAVE à l’aide de DMF :
dmls, dmget, dmput
$HOME_WORK non sauvegardés
Quota disques :
quota -v
Assistance :
http://www.crihan.fr/assistance/tickets-illiac8.html
Consommation CPU :
http://www.crihan.fr/CRIHAN/calcul/compta.html
Documentation utilisateur :
http://www.crihan.fr/CRIHAN/calcul/par/doc/Illiac8/index.html

1- D. Environnement batch
Mode batch = traitement des commandes par lots
préparation d’un ensemble de commandes dans un fichier (script), un “job”
soumission à NQE (Network Queueing Environment) (cqsub) :
=> Recherche d’une queue batch éligible selon les ressources demandées
=> cqstatl -a
=> transmis à NQS si les ressources sont disponibles
=> mis en attente, status “pending”
NQS (Network Queueing System) vérifie les limites des queues batch
=> qstat -a
=> running (Rxx)
=> queueing (Qyy)  -> signification de yy : manpage de qstat
Priorité d’exécution des "jobs" en fonction des ressources demandées.

1- D. Environnement batch
Utilisation du batch :
Rajouter dans votre home le fichier .nqshosts : illiac8.crihan.fr
Création du script
Paramètres CQSUB :
-lM : fixe la mémoire maximale de la requête
=> somme des mémoires résidentes (colonne RES de top)
-lm : fixe la mémoire maximale par processus
=> mémoire virtuelle maximale (colonne SIZE de top)
-lT : fixe le temps CPU maximal de la requête
-lt : fixe le temps CPU maximal par processus
-l mpp_p=nb_procs : fixe le nombre maximal de processeurs utilisés
!!!  MPI, OpenMP, PVM nécessitent “nb_procs +1” comme arguments
pour “-l mpp_p”

1- D. Environnement batch
#QSUB -r omp                                         ß nom du job soumis
#QSUB -u gm                                          ß login de l’utilisateur
#QSUB -x                                                 ß passage des variables d’environnement
#QSUB -eo                                               ß fusion fichier de log et fichier d’erreur
#QSUB -lM 1Go                                       ß mémoire maximale de la requête
#QSUB -lm 600Mo                                   ß mémoire maximale par processus
#QSUB -lT 1300                                       ß temps CPU maximal de la requête
#QSUB -lt 300                                          ß temps CPU maximal par processus
#QSUB -me                                              ß envoi d’un mail à la fin du job
#QSUB -mu gm@crihan.fr                     ß adresse e-mail pour l’envoi
#QSUB -l mpp_p=5                                 ß nombre de processus maximal du job
setenv OMP_NUM_THREADS 4
echo "Lancement MASTER”
cd /crihan/gm/OMP
timex ./a.out

1- D. Environnement batch
Lancement :
cqsub run_batch
Contrôle de l’exécution :
cqstatl -a                              ß au niveau de NQE
qstat -a                                 ß au niveau de NQS
Destruction :
cqdel -k identifier (txxxxx ou yyyyy.illiac8.crihan.fr)

1- D. Environnement batch
GM-illiac8% qstat -a
----------------------------------
NQS 3.3.0.15 BATCH REQUEST SUMMARY
----------------------------------
IDENTIFIER    NAME    USER     LOCATION/QUEUE        JID  PRTY REQMEM REQTIM ST
------------- ------- -------- --------------------- ---- ---- ------ ------ ---
432.illiac8.crihan.fr V_N32  gm   mem64@illiac8    635267   20      4  14999 R05
429.illiac8.crihan.fr V_64   gm   big64@illiac8             48  10000  45000 Qgm
GM-illiac8% cqstatl -a
-----------------------------
NQE 3.3.0.15 Database Task Summary
-----------------------------
IDENTIFIER           NAME    SYSTEM-OWNER     OWNER    LOCATION            ST
-------------------- ------- ---------------- -------- ------------------- ----
t411 (429.illiac8.c) V_64    lws.illiac8      gm       nqs@illiac8         NSubm
t414 (432.illiac8.c) V_N32   monitor.main     gm       NQE Database        NComp

2- Outils d’aide au développement
A. Static Analyser : cvstatic
B. Build Manager : cvbuild / cvmake
C. Debugger : cvd
D. Performance Analyser : cvperf
E. Parallel Analyser : cvpav
F. Speedshop /  perfex

2- Outils A. Static Analyser (cvstatic)
Aide à l’analyse et à la documentation de programmes
la structure du programme,
les fichiers qui le constituent,
les arbres d’appel,
les listes de fonctions,
le suivi des variables.
Deux modes d’analyse :
mode scanner : mode rapide, sans analyse relative au langage de programmation,
=> vue d’ensemble du programme.
mode parser : analyse relative au langage de programmation, possibilité de faire des interrogations.
=> étude plus poussée.

2- Outils A. Static Analyser
Commande de lancement : cvstatic ou à partir de cvd
Démarche :
création d’un fileset : sélection des fichiers, du langage, option Admin/Edit FileSet,
=> création d’une base de données de références croisées,
interrogations à l’aide de requêtes classées par thèmes, menu Queries,
visualisation graphique possible par l’option View/Call Tree View,
sauvegarde des requêtes précédentes, menu History,
filtrage des sorties, option Admin/Results Filter.

2- Outils A. Static Analyser

2- Outils B. Build Manager (cvmake)
Aide à la compilation de programmes
Composé de :
Build View,
Build Analyser.
A l’aide d’une interface graphique, le Build View permet de :
compiler des programmes,
corriger les erreurs de compilation,
visualiser les sources.
Commande de lancement : cvmake ou à partir de cvd.

2- Outils B. Build Manager (cvbuild)
A l’aide d’une interface graphique, le Build Analyser permet de :
visualiser les inter-dépendances entre les fichiers,
déterminer les cibles obsolètes à compiler/recompiler, option Admin/Refresh Graph Display,
faire des interrogations, menu Query.
Commande de lancement : cvbuild ou à partir de cvd.

2- Outils B. Build Manager

2- Outils C. Debugger (cvd)
Aide au déboguage
Compilation avec les options –O0 –g3 –DEBUG:…
Constitué de :
Un éditeur, Source View,
Une barre de menus,
Un panneau de contrôle,
Une ligne d’état,
Une ligne de commande.
Commande de lancement : cvd.

2- Outils C. Debugger
Menu Admin : configuration du débogueur.
Menu Trap : gestion des points d’arrêts conditionnels/inconditionnels.
Menu PC : interaction avec le Program Counter.
Menus Display et Query : gestion de l’affichage et interrogation.
Menu View : visualisation.
Variable Browser : affichage des variables du sous-programme courant
Expression View : évaluation de formules utilisant les variables
Call Stack View : affichage de la hiérarchie des appels de fonctions

2- Outils C. Debugger

2- Outils D. Performance Analyser (cvperf)
Outil d’analyse des performances de codes.
recueil et visualisation des informations de profilage (coûts cpu des routines et des lignes sources),
utilisation de la mémoire,
Recherche des exceptions flottantes (underflow, overflow, …).
Compilation du code avec le niveau d’optimisation –O3
Commande de lancement : cvperf ou à partir de cvd
Version graphique de prof et ssrun

2- Outils D. Performance Analyser
Démarche d’instrumentation :
Choix du type de données et de la fréquence de l’échantillonnage,
Sampling Data : comptage du nombre d’exécutions d’un bloc d’instructions
Tracing Data : récupération des évènements altérant les performances
Sélection de la tâche : option Perf/Select Tasks
Instrumentation de l’exécution : bouton run
Analyse des résultats : option Perf/Examine Results

2- Outils D. Performance Analyser

2- Outils E. Parallel Analyser (cvpav)
Aide à la parallélisation automatique (APO) et à la parallélisation par directives (OpenMP).
Compilation avec le niveau d’optimisation –O3 (Loop Nest Analyser : analyse des boucles).
Examen du code source, indications à l’aide de symboles.
Insertion de directives pour le compilateur, définition de régions parallèles.
Commande de lancement : cvpav ou à partir de cvd

2- Outils E. Parallel Analyser

2- F. SpeedShop
ssrun : génère les fichiers de statistiques (ssrun [options] prgm)
-pcsamp : statistiques sur le Program Counter,
-usertime : temps (inclusif et exclusif) du programme,
-ideal : statistiques de comptage pour les blocs basiques.
ssaggregate : fusionne les fichiers d’analyse
ssaggregate –e files.exp.pid –o file.exp
prof : traite les données et établit un rapport (prof [options] file.exp)
-lines : fournit les numéros des lignes des sous-programmes,
-q n :  tronque la sortie après les n premiers sous-programmes affichés.
perfex : compte les évènements matériels (perfex -a -x -y prgm)
=> nombres de cycles, accès mémoire en dehors du cache, …

2- F. SpeedShop

2- F. SpeedShop

3- Optimisation scalaire
A. Ecriture du code,
B. Bibliothèques scientifiques,
C. Modularité,
D. Déboguage / validation,
E. Analyse des performances,
F. Optimisations par re-écriture,
G. Optimisations par options de compilation
H. Variables d’environnement.

3- Optimisation  A. Ecriture du code
Réflexion au préalable sur papier,
Algorithmes performants (!),
Déclaration explicite de toutes les variables et des fonctions externes :
Directive IMPLICIT NONE dans tous les fichiers source,
Type générique pour les variables (REAL, INTEGER),
Précision imposée à la déclaration : REAL(rp) avec rp=4 ou 8,
Appels aux noms de fonctions génériques, exemple : SQRT au lieu de DSQRT,
Séparation des types dans les commons : CHARACTER et LOGICAL à part.

3- Optimisation  A. Ecriture du code
Déclaration explicite des dimensions des tableaux,
Initialisation explicite des variables avant leur utilisation,
Indentation du source pour le rendre plus lisible,
Code aéré avec des commentaires,
Tests arithmétiques flottants selon la précision machine :
Bon :     IF ( ABS(reel1 - reel2) .LT. machep ) THEN ...
Mauvais : IF ( reel1 .EQ. reel2 ) THEN ...
Bon :     IF ( ABS(DET) .LT. machep) THEN ...
Mauvais : IF ( DET .EQ. 0 ) THEN ...

3- Optimisation  A. Ecriture du code
Précision des constantes scalaires :
INTEGER, PARAMETER  ::  rp = KIND(1.0D0)  !  rp = 8
REAL(rp)  ::  x                           !  REAL*8  ::  x
x = 2.0    / 3.0    = 0.66666668653488159
x = 2.0_rp / 3.0_rp = 0.66666666666666663
Tests arithmétiques flottants selon la précision machine :
    machep = 1.0_rp
    DO WHILE (machep + 1.0_rp > 1.0_rp )
       machep = 0.5_rp * machep
    END DO
    machep = 2.0_rp * machep
Fonction epsilon du Fortran 90

3- Optimisation  B. Bibliothèques scientifiques
Ensembles de sous-programmes testés, validés, optimisés.
=> Gain de temps et de travail et applications portables.
=> sources et documentations diverses : http://www.netlib.org
BLAS : algèbre linéaire de base (blas 1, 2, 3)
LAPACK : algèbre linéaire poussé
FFT : transformées de Fourier rapides, convolution (portabilité !)
Version SGI dans SCSL : link avec –lscs_i8 ou -lscs_i8_mp
_i8 : INTEGER*8 au lieu de INTEGER*4
Bibliothèque mathématique : link avec -lfastm au lieu de -lm

3- Optimisation  C. Modularité
Fractionner le source,
Mettre un sous-programme par fichier,
Mettre un module, un common par fichier,
Construire des bibliothèques thématiques,
Travailler avec un fichier Makefile,
Gestion des fichiers de reprise,
Tester les routines après écriture sur des exemples.

3- Optimisation  D. Déboguage / validation
Options de compilation recommandées:
-O0 : aucune optimisation !
-u : signale les variables non déclarées  (mettre IMPLICIT NONE dans le code),
-g3 : enrichir la table des symboles pour le débogueur (dbx, cvd),
-fullwarn : recevoir un maximum (-woff num) d’informations du compilateur,
-DEBUG:trap_uninitialized=ON : mise à NaN des variables non initialisées,
-DEBUG:subscript_check=ON : vérification des indices pour les tableaux,
-DEBUG:div_check=3 : vérification des quotients d’entiers et des overflows,
-DEBUG:verbose_runtime=ON : informations lors de l’exécution,
-lfpe : recherche des exceptions flottantes + variable d’environnement TRAP_FPE

3- Optimisation  E. Analyse des performances
Compilation avec le niveau d’optimisation -O3
Speedshop :
code séquentiel ou OpenMP : ssrun  -[f]pcsamp[x]  prgm
code MPI : mpirun –np nbproc ssrun –[f]pcsamp[x] prgm
fusion : ssaggregate –e prgm.exp.pids –o prgm.ssrun
analyse : prof  -lines  prgm.pcsamp
Workshop:
cvperf (version graphique de ssrun/prof)
=> Localiser la consommation du cpu pour optimiser les zones coûteuses

3- Optimisation F. Optimisation par re-écriture
Opérations en virgule flottante :
=> remplacer une multiplication par une addition (coût divisé par 2) :
z = 2.0_rp * y   =>  z = y + y
=> remplacer une division par une multiplication (coût divisé par 4) :
                                                        u = 1.0_rp / v
DO i = 1, 100                DO i = 1, 100
      A (i) = A (i) / v  =>     A (i) = A (i) * u
END DO                       END DO
=> risque de perte de précision

3- Optimisation F. Optimisation par re-écriture
Optimisation des boucles :
réduire les boucles extérieures en cas de boucles imbriquées,
prendre un schéma d’adressage qui ne bride pas les performances
    DO j=1,M      DO j=1,M          DO j=1,M         DO j=1,M
       DO i=1,N      DO i=1,N          DO i=1,N         DO i=1,N
         A(i,j)        A(i+(j-1)*N)      k=k+1            A( index(i,j) )
                                         A(k)
       END DO        END DO            END DO           END DO
    END DO        END DO            END DO           END DO
      ++        +           -          --
fusionner des boucles consécutives ayant les mêmes bornes d’utilisation.
=> Fournir des opportunités pour les optimiseurs.

3- Optimisation F. Optimisation par re-écriture
Optimisation des tests :
la présence de tests booléens inhibe le travail des optimiseurs
=> les remplacer par des fonctions arithmétiques intrinsèques .
rmax = 0.0
DO i = 1, N
IF ( ABS(V(I)) > rmax ) rmax = V(I)
END DO
devient
rmax = 0.0_rp
DO I = 1, N
rmax = MAX( rmax, ABS( V(I) ) )
END DO

3- Optimisation F. Optimisation par re-écriture
Optimisation mémoire :
Aligner les données en mémoire (plus rapide car minimise les accès mémoire),
Accéder aux tableaux de la même façon qu’ils sont stockés :
En Fortran parcours suivant les colonnes :        En C parcours suivant les lignes :
DO i = 1, n                      for (i=1; i < (n+1); i++) {
  DO j = 1, n                       for (j=1; j < (n+1); j++) {
     A (i,j) = B (i,j) lent            A[i][j] = B[i][j]; rapide
     C (j,i) = D (j,i) rapide          C[j][i] = D[j][i]; lent
  END DO                            }
END DO                           }

3- Optimisation F. Optimisation par re-écriture
Utiliser des algorithmes qui ont une approche locale des variables :
=> travail sur des données contiguës, minimiser la navigation aléatoire dans de gros volumes de données (adressage indirect)
Utiliser des algorithmes “par blocs” (cas d’opérations matricielles) :
=> travailler sur des blocs de données qui rentrent dans le cache de données
=> Augmentation des performances si :
1. nombre d’itérations >> nombre de données utilisées,
2. Les boucles sont permutables,
3. taille du bloc < taille du cache disponible.
=> le compilateur essaye de le faire lors de boucles imbriquées (cache blocking)
=> principe …

3- Optimisation F. Optimisation par re-écriture
                            DO j1 = 1, n, jblock
                               j2 = min (j1 + jblock - 1, n)
                               DO i1 = 1, m, iblock
                                  i2 = min (i1 + iblock - 1, m)
DO j = 1, n                       DO j = j1, j2
      DO i = 1, m                    DO i = i1, i2
         ...         ==>>               ...
      END DO                         END DO
END DO                            END DO
                               END DO
                            END DO
Règle : “nb_tab*iblock*jblock*sizeof(real) < 0.90 * cache L1 en octets”
Rmq : j2= min(j1+jblock-1,n) bien meilleur que   IF (j1+jblock-1 > n) j2= n

3- Optimisation F. Optimisation par re-écriture
Librairie de gestion rapide de la mémoire : link avec -lmalloc en C
Allouer une grosse zone mémoire que l’on redistribue plutôt que de nombreux petits blocs
=> le but est à chaque fois de donner des opportunités pour optimiser une boucle, réarranger des opérations pour une meilleure efficacité :
maximiser l’utilisation des registres.
Optimiser les I/O (Entrées/Sorties)
I/O = lectures/écritures de données  =>  pertes de performances,
éviter les fichiers temporaires, garder les données en mémoire,
rediriger les I/O du terminal (clavier/écran) vers des fichiers,
chemins d’accès courts, répertoires non surpeuplés.

3- Optimisation F. Optimisation par re-écriture
I/O de deux types :
I/O formatées : traduction des données sous forme de caractères à l’aide d’un descripteur;
I/O non formatées : transfert des données sans les éditer.
=> architecture-dépendant
Remplacer                                        par
DO i = 1, N
   write (21)  A(i)          write (21) A
ENDDO
Employer les fonctions C (gain : 20%) : printf
Utilisation des I/O :
post-processing, représentation graphique : I/O formatées;
fichiers de reprise (impératif à prévoir dans un code !) : I/O non formatées.

3- Optimisation G. Optimisation par options
Optimisation gérée par options de compilation : -On
Option -O0 : aucune optimisation
Valeur par défaut sur SGI,
Utilisation pour le déboguage.
Option -O1 : optimisations locales
Au niveau des instructions MIPS par les générateurs assembleur et code,
Superposition des instructions sur les réels,
Remplissage des temps d’attente (lecture/écriture en mémoire),
Sauvegarde des résultats des registres,
Élimination de code inutile car sans effet.

3- Optimisation G. Optimisation par options
Option -O2 (-O) : optimisations globales
Transformations du code,
Étude des dépendances à l’intérieur des procédures,
Minimisation des lectures/écritures en mémoire,
Déroulement des boucles,
=> Niveau maximal d’optimisation sans risque de perte de précision.
Option -O3 : optimisations agressives
Optimisations plus poussées
Couplage avec d’autres options :
-OPT (Optimization options, man opt) : précision sur les calculs en flottants,
-LNO (Loop Nest Optimizer, man lno) : optimisation des boucles,
-IPA (Inter Procedural Analysis, man ipa) : analyse interprocédurale,inlining.
=> Pertes de précision potentielles, comparer les résultats.

3- Optimisation G. Optimisation par options
Option -Ofast : optimisations maximales
-Ofast=ip27 : maximalise les performances en tenant compte de l’architecture de la machine
pertes de précision probables dûes au réarrangement des opérations.
Bibliothèque mathématique : -lfastm
Configuration maximale :
-n32/-64  -r10000  -mips4  -Ofast=ip27  -OPT:IEEE_arithmetic=3:roundoff=3
Configuration conseillée :
-n32/-64  -r10000  -mips4  -O3  -OPT:IEEE_arithmetic=1:roundoff=0
F90 (allocation dynamique, modules, interfaces…) :
la norme F77 est incluse dans la norme F90.

3- Optimisation G. Optimisation par options

3- Optimisation G. Optimisation par options
-flist : résultat de la compilation après optimisations;
-auto_use mpi_interface : vérification des appels à des routines MPI;
-r8 / -i8 / -d8 : réels, entiers, doubles précisions sur 64 bits;
-col120 : source sur 120 colonnes au lieu de 72;
manpages utiles (à lire !) :
f77, f90, cc, CC, ld : compilation / édition de liens;
opt, lno, ipa, debug_group : optimisation, déboguage;
mp : parallélisation;
pe _environ : variables d’environnement;
handle_sigfpes, sigfpe : exceptions flottantes.

3- Optimisation H. Variables d’environnement
Déboguage
traitement exceptions flottantes : TRAP_FPE + librairie libfpe
setenv TRAP_FPE
”ALLCOUNT;UNDERFLOW=ZERO;OVERFL=TRACE(2),ABORT(2);INVALID=TRACE(2),ABORT(2)”
TRACE(n) : affiche des n premiers, ABORT(p) : arrêt au p-ième
traitement débordement de tableaux
setenv F90_BOUNDS_CHECK_ABORT YES (arrêt demandé)
traitement débordement de tableaux F90
setenv F90_CONFORM_CHECK_ABORT YES (arrêt demandé)
Optimisation
garder le même processeur pour un processus
setenv _DSM_MUSTRUN

4- Parallélisme
A. Définitions / Présentations
B. Parallélisme par échanges de messages
C. Parallélisme à mémoire partagée
D. Analyses de performances

4- Parallélisme A. Définition
Principe du parallélisme :
“Diviser pour régner”
Une définition du parallélisme :
Ensemble de techniques logicielles et matérielles permettant l’exécution simultanée de séquences d’instructions indépendantes, sur des processeurs différents

4- Parallélisme A. Programmations parallèles
Parallélisme SMP (Shared Memory Processing)
OpenMP (http://www.openmp.org)
Parallélisme par échanges de données (Massively Parallel Processing)
MPI (http://www.mpi-forum.org),
PVM (http://www.epm.ornl.gov/pvm/pvm_home.html),
SHMEM (spécifique SGI/CRAY … portage chez d’autres constructeurs)
Parallélisme de données HPF (Portland Group)
http://www.pgroup.com
Parallélisme mixte MPP&SMP
échanges de messages + SMP

4- Parallélisme A. Types de parallélisme
Parallélisme de données
Données régulières et en grand nombre
Traitement identique sur chaque donnée
=> Programmation Data-parallèle
Le parallélisme découle de l’application simultanée du même traitement sur des données différentes
Parallélisme de tâches
Plusieurs traitements
Traitements indépendants
=> Echanges de données, directives de contrôle
Le parallélisme découle de la réalisation simultanée de différents traitements sur les données

4- Parallélisme A. Modèles de programmation
Implicite :
Paralléliseurs automatiques : APO
Directives parallélisme à mémoire partagée : OpenMP
Outils Data-parallèle : HPF
Explicite :
Echanges de messages : MPI, PVM
Copie de mémoire à mémoire : SHMEM

4- Parallélisme  B. Par échange de données

4- Parallélisme  B. Par échange de données
Modèle de programmation explicite :
Communications et synchronisations à la charge du programmeur
Echanges de données par messages
MPI et PVM
programmation portable
MPI norme (modèle à privilégier)
PVM standard (en voie de disparition)
Echanges de données par mémoire partagée
copie de mémoire à mémoire
SHMEM : modèle propriétaire (supporté par Compaq)

4 Parallélisme B. MPI : Message Passing Interface
Création d’un programme parallèle SPMD
Lancement de l’exécutable en parallèle sur n processus

4- Parallélisme B. MPI : environnement
Environnement parallèle :
activation : MPI_INIT (irc)
désactivation : MPI_FINALIZE (irc)
Communicateur : “univers de communication”
=> Ensemble de processus actifs
rang (identité) : MPI_COMM_RANK (MPI_COMM_WORLD, mon_rang, irc)
Nombre de processus : MPI _COMM_SIZE (MPI_COMM_WORLD, nbproc, irc)
INTEGER  ::  irc = 0
INTEGER  ::  mon _rang, nbproc
=> exemple 1

4- Parallélisme B. MPI : échange de messages
Message = donnée à transmettre entre des processus;
Informations nécessaires :
processus source(s),
type de la donnée,
longueur,
étiquette (tag),
processus destinataire(s);
Communications entre 2 processus : point-à-point;
Comunications entre plusieurs processus : collectives.

4- Parallélisme B. MPI : point-à-point
=> communications entre 2 processus : source et destinataire
Paramètres de la communication :
processus identifiés par leur rang dans le communicateur,
données,
types des données :  MPI_INTEGER, MPI _REAL, MPI _COMPLEX, MPI_LOGICAL, MPI _CHARACTER, ...
longueur des données,
étiquette,
communicateur.

4- Parallélisme B. MPI : point-à-point
Communication bloquante : attendre la fin de la
communication avant de continuer l’exécution.
Envoi :
MPI _SEND (don, taille, type, dest, tag, comm, irc)
Envoi d’un message identifié tag, de taille taille, de type type, à partir de l’adresse don,
au processus dest, dans le communicateur comm.
Réception :
MPI _RECV (don, taille, type, source, tag, comm, statut, irc)
INTEGER, DIMENSION (MPI _STATUS _SIZE)  ::  statut
Réception d’un message identifié tag, de taille taille, de type type, placé à partir de
l’adresse don, du processus source, dans le communicateur comm.
=> exemple 2

4- Parallélisme B. MPI : point-à-point
Communication non bloquante : suite de l’exécution sans
attendre la réception ou la fin de la communication.
=> possibilité de recouvrement de la communication par du
calcul mais il faut s’assurer de l’envoi et de la réception;
=> fonctions de vérification, d’attente.
Envoi :
MPI _ISEND (don, taille, type, dest, tag, comm, requete, irc)
Envoi d’un message identifié tag, de taille taille, de type type, à partir de l’adresse don, au processus dest, dans le communicateur comm.
requete identifie l’envoi (différent de tag).
INTEGER  ::  requete

4- Parallélisme B. MPI : point-à-point
Réception :
MPI _IRECV (don, taille, type, source, tag, comm, requete, irc)
Réception d’un message identifié tag, de taille taille, de type type, placé à partir de l’adresse don, du processus source, dans le communicateur comm.
Validation :
MPI _TEST (requete, flag, status, irc)
LOGICAL  ::  flag
Attente :
MPI _WAIT (requete, status, irc)
Libération :
MPI _REQUEST _ FREE (requete, irc)
=> exemple 3

4- Parallélisme B. MPI : collectives
Tous les processus d’un même communicateur sont impliqués.
Communication collective = plusieurs communications point-à-point en une seule opération avec possibilité d’effectuer une opération sur les données.
Pas de gestion des étiquettes.
3 types de communications collectives :
synchronisation globale : MPI _BARRIER (comm, irc);
diffusion simple;
diffusion avec opération sur les données.

4- Parallélisme B. MPI : collectives
Diffusion simple :
Diffusion globale : MPI_BCAST (don, taille, type, source, comm, irc)
Envoi par le processus source, à tous les processus de comm, d’un message de taille taille, de type type, à partir de l’adresse don.
Diffusion sélective :
MPI_SCATTER (sdon, staille, stype, rdon, rtaille, rtype, source, comm, irc)
Diffusion sélective de données réparties, par tous les processus : MPI_ALLTOALL (sdon, staille, stype, rdon, rtaille, rtype, comm, irc)
Collecte de données réparties :
MPI_GATHER (sdon, staille, stype, rdon, rtaille, rtype, source, comm, irc)
Collecte de données réparties, par tous les processus :
MPI_ALLGATHER (sdon, staille, stype, rdon, rtaille, rtype, comm, irc)

4- Parallélisme B. MPI : collectives

4- Parallélisme B. MPI : collectives
Diffusion et opérations sur les données
=> opération de réduction = appliquer la même opération sur des valeurs réparties entre les processus.
=> opérations prédéfinies : MPI _MAX, MPI _MIN, MPI _SUM, ...
MPI _REDUCE (don, res, taille, type, oper, dest, comm, irc)
Depuis tous les processus de comm, envoi d’un message de taille taille, de type type, à partir de l’adresse don, faire l’operation oper sur ces valeurs. Réception du résultat res par le processus dest.
=> exemple 4
MPI _ALLREDUCE = MPI _REDUCE  + MPI _BCAST

4- Parallélisme B. MPI : environnement
Version MPI : 1.2 + (grandes évolutions en ver 2.0)
Fichier .rhosts dans le home : illiac8.crihan.fr login
Includes : mpif.h ou module MPI en f90 (fortran) ou mpi.h (C)
Bibliothèque : libmpi.so (C et fortran)
version 32 ou 64 bits appelée en fonction de l’option -n32 ou -64 lors de la compilation et l’édition de liens (-lmpi)
Commande d’exécution : /usr/bin/mpirun
 ex : mpirun -np nb_proc pgm
!!! #QSUB -l mpp_p=“nb_proc”+1
Manpages : mpi, mpirun, pe_environ, mpi_send, …
Variables : setenv MPC_GANG OFF, MPI_DSM_MUSTRUN, MPI_DSM_PPM 1

4- Parallélisme B.Conclusions échange de données
Avantages :
parallélisation à gros grains
portabilité de l’application MPI (ou PVM)
(SHMEM reste liée à SGI/CRAY mais supportée par Compaq,...)
Inconvénients :
Développement de l’application tout ou rien
pas d’outil de parallélisation automatique

4- Parallélisme B. Mise en œuvre sur Illiac8
MPT : Message Passage Toolkit (ver. 1.4)
ensemble logiciel pour la programmation par échange de messages : MPI, PVM, SHMEM;
installation statique: rien à faire !
anciennes versions, commande : module avail / list / load / unload
Initialisation de l’environnement (variables d’environnement, chemins, librairies, fichiers inclus, …).
mpt1.3 : adressage 64 bits (> 2Go), version 1.3 de mpt
mpt.1.3.n32_mips4 : adressage 32 bits (< 2Go), version 1.3 de mpt
=> prendre la version 32bits, généralement suffisante.

4- Parallélisme C. A mémoire partagée
Motivation : pas de standard portable pour le SMP  => OMP
(http://www.openmp.org)
F77 et C; évolution vers C++, syntaxe F90
Modèle implicite
Parallélisation “gros grains” et “petits grains”
Basé sur le principe du fork & join :
création d’une équipe de threads à l’entrée
d’une région parallèle dont le nombre est controlé
par variable d’environnement ou appel librairie.

4. Parallélisme C. OpenMP : directives
OpenMP est un ensemble de constructions bâties sur des directives et leurs clauses, qui sont des commentaires structurés commençant par une sentinelle :
!$OMP   … &   format       ou    C$OMP        format
!$OMP             libre                  C$OMP+ …  fixe
Parallélisation d’une région :
!$OMP PARALLEL [clauses]
!$OMP END PARALLEL
=> ces directives doivent être présentes dans le même sous-programme(fichier)
=> la région parallèle est constituée des instructions entre ces deux directives (portée lexicale) et des sous-programmes appelés au sein de la région;
=> les branchements hors d’une région parallèle sont interdits;
=> sa création peut être conditionnelle.

4. Parallélisme C. OpenMP : clauses
PRIVATE : arguments privés à chaque thread mais indéfinis,
SHARED : arguments visibles pour toutes les threads,
DEFAULT : imposer un attribut à tous les arguments de la zone parallèle,
FIRSTPRIVATE : arguments privés à chaque thread et initialisés,
LASTPRIVATE(*1) : arguments privés à chaque thread, impose la dernière valeur en sortie,
REDUCTION : opération de réduction sur les arguments,
IF(*2) : clause conditionnelle d’exécution en parallèle,
COPYIN : copie de blocs common vers les threads.
(*1) la clause LASTPRIVATE est spécifique aux boucles;
(*2) la clause IF est spécifique aux régions parallèles;
=> les clauses permettent de délimiter la visibilité des variables au sein des constructions (régions, boucles, …).

4. Parallélisme C. OpenMP : région parallèle
INTEGER  ::  rank = 0
INTEGER  ::  nbthrds = 1
!$OMP PARALLEL DEFAULT (NONE) &
!$OMP SHARED (nbthrds) &
!$OMP PRIVATE (rank)
!$OMP MASTER
!$    nbthrds = OMP_GET_NUM_THREADS ()
!$OMP END MASTER
!$OMP BARRIER
!$    rank = OMP_GET_THREAD_NUM ()
      write (6,*) ‘rang = ‘, rank, ‘ sur ‘, nbthrds, ‘ processus’
!$OMP END PARALLEL

4. Parallélisme C. OpenMP : section parallèle
Parallélisation par section (mode MPMD) :
!$OMP PARALLEL SECTIONS, &
!$OMP SHARED (a,b)
!$OMP SECTION
      CALL work1 (a)
!$OMP SECTION
      CALL work2 (b)
!$OMP END SECTIONS
!$OMP END PARALLEL
=> chaque section est exécutée par une unique tâche,
=> méthode non scalable,
=> les directives SECTIONS / SECTION / END SECTIONS doivent figurer dans le même sous-programme (fichier)

4. Parallélisme C. OpenMP : boucle parallèle
=> boucle avec indices entiers,
=> bornes identiques pour toutes les tâches,
=> directive PARALLEL DO = région parallèle limitée à la prochaine boucle.
!$OMP PARALLEL DO DEFAULT (NONE), PRIVATE (I,J) &
!$OMP FIRSTPRIVATE (alpha, beta, N, M) &
!$OMP SHARED (A, B, C, D)
      DO J = 1, N
         DO I = 1, M
            A(I,J) = alpha * B(I,J) + beta * ( C(I,J) + D(I,J) )
         END DO
      END DO
!$OMP END PARALLEL DO

4. Parallélisme C. OpenMP : boucle parallèle
=> boucle privée :
!$OMP PARALLEL DEFAULT(NONE) &
!$OMP&PRIVATE (I, J, A) &
!$OMP&SHARED (B, C, N, M)
      DO J = 1, N                       <-- boucle dupliquée
         DO I = 1, M                    <-- boucle dupliquée
            A(I,J) = B(I,J) + C(I,J)
         END DO
      END DO
      ...
      CALL WORK (A,N,M)     <-- copie privée de A par processus
!$OMP END PARALLEL
=> toutes les tâches exécutent la boucle.

4. Parallélisme C. OpenMP : boucle parallèle
=> boucle partagée :
!$OMP PARALLEL DEFAULT(NONE) &
!$OMP&PRIVATE (I, J) &
!$OMP&SHARED (A, B, C, N, M)
!$OMP DO
      DO J = 1, N                       <-- boucle partagée
         DO I = 1, M                    <-- boucle dupliquée
            A(I,J) = B(I,J) + C(I,J)
         END DO
      END DO
!$OMP END DO
      ...
      CALL WORK (A,N,M)     <-- variable A partagée
!$OMP END PARALLEL
=> chaque tâche n’exécute qu’une partie des itérations.

4. Parallélisme C. OpenMP : boucle parallèle
!$OMP PARALLEL DEFAULT (NONE) &
!$OMP SHARED (A,B,Y,Z,N,M) &
!$OMP PRIVATE (I)
!$OMP DO
      DO I = 2, N
         B (I) = 0.5_rp * ( A (I) + A (I-1) )
      END DO
!$OMP END DO [NOWAIT]          <- on peut ne pas synchroniser
!$OMP DO
      DO I = 1, M
         Y (I) = SQRT( Z (I) )
      END DO
!$OMP END DO [NOWAIT]
!$OMP END PARALLEL

4. Parallélisme C. OpenMP : boucle parallèle
clause d’ordonnancement
!$OMP PARALLEL DO SCHEDULE (type, chunk)
ou
!$OMP DO SCHEDULE (type, chunk)
=> 4 modes de répartition
mode static : paquets de taille fixe, chunk si précisé,
affectés à une tâche précise,
mode dynamic : paquets de taille fixe, chunk si précisé,
affectés à la première tâche disponible,
mode guided : paquets de taille décroissante au moins égale à chunk, affectés à la première tâche disponible,
mode runtime : choix différé à l’exécution par variable d’environnement : setenv OMP_SCHEDULE “mode,chunk”

4. Parallélisme C. OpenMP : réduction
!$OMP PARALLEL DO DEFAULT (NONE), REDUCTION (+: err, somme)&
!$OMP PRIVATE (I,J,T), SHARED (N, M, A, B, C, err, somme)
      DO J = 1, N          <-- boucle parallélisée + réduction
         DO I = 1, M       <-- boucle dupliquée
            T = A(I,J) - B(I,J)
            somme = somme + T
            err = err + T * ( A(I,J) + B(I,J) )
         END DO
      END DO
!$OMP END PARALLEL DO
=> variable lue et mise à jour par une tâche à la fois,
=> variable publique (shared), de type scalaire intrinsèque,
=> opérateurs associatifs usuels,
=> somme et err sont des instances privées jusqu’à la fin.

4. Parallélisme C. OpenMP : exécution unique
!$OMP PARALLEL DO DEFAULT (NONE) &
!$OMP SHARED (nbproc)
!$OMP MASTER
      nbproc = 1
!$    nbproc = OMP_GET_NUM_THREADS ()
      WRITE (6,*) ‘Nombre de threads : ‘, nbproc
!$OMP END MASTER        <- pas de barrière de synchronisation incluse
!$OMP BARRIER           <- peut être nécessaire
plus efficace que
!$OMP SINGLE
      nbproc = 1
!$    nbproc = OMP_GET_NUM_THREADS ()
      WRITE (6,*) ‘Nombre de threads : ‘, nbproc
!$OMP END SINGLE        <- barrière de synchronisation incluse
!$OMP END PARALLEL DO

4. Parallélisme C. OpenMP : mise à jour atomic
    somme = 0.0_rp
!$OMP PARALLEL DO DEFAULT (NONE) &
!$OMP SHARED (A, N, somme) &
!$OMP PRIVATE (I
      DO I = 1, N
!$OMP ATOMIC
         somme = somme + A (I)
      END DO
!$OMP END PARALLEL DO
=> Une seule ligne affectée, immédiatement après la directive, contrairement à MASTER …END MASTER et SINGLE …END SINGLE,
=> lecture et mise à jour par une tâche à la fois,
=> variable scalaire intrinsèque.

4. Parallélisme C. OpenMP : environnement
Gestion par variables d’environnement
OMP_SCHEDULE, OMP_NUM_THREADS, OMP_DYNAMIC.
Gestion par appel à des fonctions
OMP_SET_NUM_THREADS, OMP_GET_NUM_THREADS, OMP_GET_THREAD_NUM.
Autres variables :
DSM_PPM, DSM_MUSTRUN
Compilation (niveau d’optimisation : -O3 au minimum)
-mp : multi-processing
Exécution
setenv  OMP_NUM_THREADS   10
timex  ./a.out
!!! #QSUB -l mpp_p=“OMP_NUM_THREADS”+1

4- Parallélisme C. Conclusions mémoire partagée
Avantages :
Standard portable
Parallélisme à gros grains et petits grains
Respect de la sémantique du code séquentiel
Pas de gestions explicite des processus
Scalable
Inconvénients :
Problèmes pour les I/O parallèles

4- Parallélisme D. Analyses de performances
Accélération : A(p) = T(1) / T(p)
=> T(n) : temps écoulé pour n processus
Efficacité (en %) : E(p) = 100 x A(p) / p
Mesure par SpeedShop :
mpirun –np nbproc ssrun –fpcsampx ./a_mpi.out
setenv OMP_NUM_THREADS  nbproc
ssrun –fpcsampx ./a_omp.out
=> on obtient nbproc fichiers de la forme a_xxx.out.fpcsampx.pid

4- Parallélisme D. Analyses de performances
Load-balancing :
prof –lines a_xxx.out.fpcsampx.pid1 > xxx.pid1_ssrun  etc …
grep ‘\[1\]’ xxx.pid*_ssrun
Comparaison séquentiel / parallèle :
ssrun –fpcsampx a_seq.out
prof –lines a_seq.out.fpcsampx.pid > seq_ssrun
ssaggregate –e a_xxx.out.fpcsampx.pid* –o xxx.cumul_fpcsampx
prof –lines xxx.cumul_fpcsampx > xxx_ssrun
grep ‘subroutine’ xxx_ssrun seq_ssrun

4- Parallélisme : Conclusions
Parallélisme par échanges de messages :
=> MPI, SHMEM, PVM
Parallélisme sur mémoire partagée
=> OpenMP

Conclusions
Le portage et le développement se font en suivant des règles :
respect des normes du langage,
utilisations d’outils d’aide,
options de compilation adaptées.
 L’optimisation d’un code a plusieurs facettes :
optimisation scalaire : par re-écriture et options de compilation,
optimisations parallèles : plusieurs techniques de parallélisation possibles,
à choisir selon le profil du code et les machines d’utilisation.