Optimisation des performances et Parallélisme en C/C++ - openMP -
MPI - UPC - CUDA -openCL -
http://www.ann.jussieu.fr/pironneauOptimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCL
http://www.ann.jussieu.fr/pironneau
Cours Mastère 2, Automne 2009
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 1 /
118
Outline I 1 Leçon 1 : Architecture des machines
Principes Les environnements de travail Machines Parallèles
2 Leçon 2: architectures parallèles Les logiciels Un exemple facile
a paralléliser Le code C
3 Leçon 3: Parallélisation avec openMP Principes de openMP Exemples
et syntaxes Analyse de edostochOMP.c Plus d’exemple et de mots clés
en OpenMP Exemple 2: EDP-1d en éléments finis Discretisation par
Elements Finis P1
Parallélisation en OpenMP Olivier Pironneau (LJLL) Optimisation des
performances et Parallélisme en C/C++ - openMP - MPI - UPC - CUDA
-openCLMPE 2 / 118
Outline II Le code vanilafem.c
4 Leçon 4: Message Passing Interface Historique et résumé
Parallélisation mémoire distribuée en MPI
5 Leçon 5: UPC: Unified Parallel C UPC de Berkeley
6 Leçon 6: Les GPU, CUDA et openCL Historique Portabilité: openCL
openCL sur Mac
7 Leçon 7: Les outils du calcul parallèle le partitionneur Metis
pour les Maillages non-structurées Integration les compilateurs
dans Eclipse Bibliothèques pour le calcul parallèle PetSc
8 Leçon 8: les algorithmes du calcul parallèle Olivier Pironneau
(LJLL) Optimisation des performances et Parallélisme en C/C++ -
openMP - MPI - UPC - CUDA -openCLMPE 3 / 118
Outline III Méthodes de Schwarz Méthode de Schur Méthodes
Lagrangienne et Mortier-Joint
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 4 /
118
La machine de von Neumann
Un programme stocké en mémoire Des mémoires pour les programmes et
les données Une ou plusieurs unités de calcul et unités
logiques
La vitesse est limitée - par la vitesse du processeur - par le taux
de transfert du bus entre la mémoire et le CPU - par les conflits
entre opérations et transferts dans les machines vectorielles et
multi-coeur.
Toute les opérations sont traduites en binaire (algèbre de Boole)
et implémentées par des portes logiques (silicium). Ce mode de
fonctionnement pourrait être remis en question pour les ordinateurs
quantiques. Si les mémoires acquièrent individuellement des
fonctions de calcul on pourrait aussi revenir au principe du "data
flow".
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 5 /
118
Pointeurs et adresses
Numérotation des mémoires Chaque mémoire possède une adresse
physique, mais elle est adressée par une adresse logique qui dépend
du programme. Ainsi le système met à la disposition du programme un
bloc mémoire qui peut être vu comme contiguë même s’il ne l’est pas
en réalité. Pointeurs: relations entre la valeur stockée par une
mémoire et son adresse (logique):
// 2 blocs mémoires sont alloués, float a,b; // un pour le réel a
et un pour b float* adr;//adr est une nb de type "pointeur sur un
réel" adr = @a; //le bloc mémoire d’adresse adr contient a
*adr =b; // on recopie b dans le bloc mémoire // qui contenait a,
donc a est perdu.
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 6 /
118
Hiérarchisation des mémoires
Mémoires périphériques (lent): disque dur, clef USB, bandes
magnétiques Mémoires principales (rapide): memoire RAM Buffers
(mémoires dédiées aux communications): mémoires tampon entre le
disque dur et la RAM ou le proc. Caches (très rapide) memoire
rapide pres du processeur: maintenant dans la puce proc. Registres
(interne au microprocesseur) : en général dans la puce proc.
La situation se complique avec les machines parallèles et/ou les
machines hybrides (GPU) car il faut distinguer les mémoires
accessibles directement par le proc de celles accessible par
intéruption système (il faut demander la permission en quelque
sorte) parce qu’elles dépendent directement d’un autre processeur
par exemple.
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 7 /
118
Ordinateurs vectoriels
L’objectif est d’accélérer l’opération suivante
float x[100], y[100], z[100]; for (i = 0: i < 100: i++) z[i] =
x[i] + y[i];
Plusieurs unités de calcul flottant Amener les données dans le
cache à l’avance (fetch) Ordonner les données et faire les + en //
Ranger les données en // (store)
Tester l’option -O3 du compilateur gcc Remarque Ca ne marche pas si
bien pour
float x[100], y[100]; for (i = 1: i < 100: i++)
x[i] = x[i-1] + y[i];
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 8 /
118
CBLAS
L’objectif est d’optimiser les opérations vectorielles bas niveau
en utilisant une librairie adaptée à la machine. C’est le cas de
"BLAS"; en principe on n’a alors plus à se préoccuper des
caches.
Exemple: accélération de la méthode du gradient conjugué avec la
fonction cblas_daxpy(..) qui remplace y par αx + y . Rappel: le
gradient conjugué pour Ax=f (ou A est n × n symmétrique)
for (n = 0; n < N; n + +){ gn = Axn − f
γ = |gn|2
ρ = hn · gn
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 9 /
118
CBLAS mementoLevel 1 BLAS dim scalar vector vector scalars
5-element array prexesSUBROUTINE xROTG ( A, B, C, S ) Generate
plane rotation S, DSUBROUTINE xROTMG( D1, D2, A, B, PARAM )
Generate modied plane rotation S, DSUBROUTINE xROT ( N, X, INCX, Y,
INCY, C, S ) Apply plane rotation S, DSUBROUTINE xROTM ( N, X,
INCX, Y, INCY, PARAM ) Apply modied plane rotation S, DSUBROUTINE
xSWAP ( N, X, INCX, Y, INCY ) x$ y S, D, C, ZSUBROUTINE xSCAL ( N,
ALPHA, X, INCX ) x x S, D, C, Z, CS, ZDSUBROUTINE xCOPY ( N, X,
INCX, Y, INCY ) y x S, D, C, ZSUBROUTINE xAXPY ( N, ALPHA, X, INCX,
Y, INCY ) y x+ y S, D, C, ZFUNCTION xDOT ( N, X, INCX, Y, INCY )
dot xT y S, D, DSFUNCTION xDOTU ( N, X, INCX, Y, INCY ) dot xT y C,
ZFUNCTION xDOTC ( N, X, INCX, Y, INCY ) dot xHy C, ZFUNCTION xxDOT
( N, X, INCX, Y, INCY ) dot + xT y SDSFUNCTION xNRM2 ( N, X, INCX )
nrm2 jjxjj2 S, D, SC, DZFUNCTION xASUM ( N, X, INCX ) asum
jjre(x)jj1 + jjim(x)jj1 S, D, SC, DZFUNCTION IxAMAX( N, X, INCX )
amax 1stk 3 jre(xk)j+ jim(xk)j S, D, C, Z= max(jre(xi)j+
jim(xi)j)Level 2 BLASoptions dim b-width scalar matrix vector
scalar vectorxGEMV ( TRANS, M, N, ALPHA, A, LDA, X, INCX, BETA, Y,
INCY ) y Ax+ y; y AT x+ y; y AHx+ y;Am n S, D, C, ZxGBMV ( TRANS,
M, N, KL, KU, ALPHA, A, LDA, X, INCX, BETA, Y, INCY ) y Ax+ y; y AT
x+ y; y AHx+ y;Am n S, D, C, ZxHEMV ( UPLO, N, ALPHA, A, LDA, X,
INCX, BETA, Y, INCY ) y Ax+ y C, ZxHBMV ( UPLO, N, K, ALPHA, A,
LDA, X, INCX, BETA, Y, INCY ) y Ax+ y C, ZxHPMV ( UPLO, N, ALPHA,
AP, X, INCX, BETA, Y, INCY ) y Ax+ y C, ZxSYMV ( UPLO, N, ALPHA, A,
LDA, X, INCX, BETA, Y, INCY ) y Ax+ y S, DxSBMV ( UPLO, N, K,
ALPHA, A, LDA, X, INCX, BETA, Y, INCY ) y Ax+ y S, DxSPMV ( UPLO,
N, ALPHA, AP, X, INCX, BETA, Y, INCY ) y Ax+ y S, DxTRMV ( UPLO,
TRANS, DIAG, N, A, LDA, X, INCX ) x Ax; x AT x; x AHx S, D, C,
ZxTBMV ( UPLO, TRANS, DIAG, N, K, A, LDA, X, INCX ) x Ax; x AT x; x
AHx S, D, C, ZxTPMV ( UPLO, TRANS, DIAG, N, AP, X, INCX ) x Ax; x
AT x; x AHx S, D, C, ZxTRSV ( UPLO, TRANS, DIAG, N, A, LDA, X, INCX
) x A1x; x ATx; x AHx S, D, C, ZxTBSV ( UPLO, TRANS, DIAG, N, K, A,
LDA, X, INCX ) x A1x; x ATx; x AHx S, D, C, ZxTPSV ( UPLO, TRANS,
DIAG, N, AP, X, INCX ) x A1x; x ATx; x AHx S, D, C, Zoptions dim
scalar vector vector matrixxGER ( M, N, ALPHA, X, INCX, Y, INCY, A,
LDA ) A xyT +A;Am n S, DxGERU ( M, N, ALPHA, X, INCX, Y, INCY, A,
LDA ) A xyT +A;Am n C, ZxGERC ( M, N, ALPHA, X, INCX, Y, INCY, A,
LDA ) A xyH +A;Am n C, ZxHER ( UPLO, N, ALPHA, X, INCX, A, LDA ) A
xxH + A C, ZxHPR ( UPLO, N, ALPHA, X, INCX, AP ) A xxH + A C,
ZxHER2 ( UPLO, N, ALPHA, X, INCX, Y, INCY, A, LDA ) A xyH + y(x)H
+A C, ZxHPR2 ( UPLO, N, ALPHA, X, INCX, Y, INCY, AP ) A xyH + y(x)H
+A C, ZxSYR ( UPLO, N, ALPHA, X, INCX, A, LDA ) A xxT + A S, DxSPR
( UPLO, N, ALPHA, X, INCX, AP ) A xxT + A S, DxSYR2 ( UPLO, N,
ALPHA, X, INCX, Y, INCY, A, LDA ) A xyT + yxT +A S, DxSPR2 ( UPLO,
N, ALPHA, X, INCX, Y, INCY, AP ) A xyT + yxT +A S, DLevel 3
BLASoptions dim scalar matrix matrix scalar matrixxGEMM ( TRANSA,
TRANSB, M, N, K, ALPHA, A, LDA, B, LDB, BETA, C, LDC ) C op(A)op(B)
+ C; op(X) = X;XT ;XH ; C m n S, D, C, ZxSYMM ( SIDE, UPLO, M, N,
ALPHA, A, LDA, B, LDB, BETA, C, LDC ) C AB + C;C BA + C;C m n;A =
AT S, D, C, ZxHEMM ( SIDE, UPLO, M, N, ALPHA, A, LDA, B, LDB, BETA,
C, LDC ) C AB + C;C BA + C;C m n;A = AH C, ZxSYRK ( UPLO, TRANS, N,
K, ALPHA, A, LDA, BETA, C, LDC ) C AAT + C;C ATA+ C;C n n S, D, C,
ZxHERK ( UPLO, TRANS, N, K, ALPHA, A, LDA, BETA, C, LDC ) C AAH +
C;C AHA+ C;C n n C, ZxSYR2K( UPLO, TRANS, N, K, ALPHA, A, LDA, B,
LDB, BETA, C, LDC ) C ABT + BAT + C;C ATB + BTA+ C;C n n S, D, C,
ZxHER2K( UPLO, TRANS, N, K, ALPHA, A, LDA, B, LDB, BETA, C, LDC ) C
ABH + BAH + C;C AHB + BHA+ C;C n n C, ZxTRMM ( SIDE, UPLO, TRANSA,
DIAG, M, N, ALPHA, A, LDA, B, LDB ) B op(A)B;B Bop(A); op(A) = A;AT
; AH ; B m n S, D, C, ZxTRSM ( SIDE, UPLO, TRANSA, DIAG, M, N,
ALPHA, A, LDA, B, LDB ) B op(A1)B;B Bop(A1); op(A) = A;AT ; AH ; B
m n S, D, C, Z2 Olivier Pironneau (LJLL) Optimisation des
performances et Parallélisme en C/C++ - openMP - MPI - UPC - CUDA
-openCLMPE 10 / 118
CBLAS
}
cblas est adapté du Fortran: blas1, blas2, blas3 Intégré a atlas et
blitz (mais attention pour la suite) sur edpblas.cpp le cpu est
divisé par 3!
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 11 /
118
Le même en C++ (I)
#include<stdio.h> #include<time.h> const int n=5000,
niter=200; void atimesx(double** A, double* x, double* f){ for(int
i=0;i<n;i++){
f[i]=0; for(int j=0;j<n;j++) f[i] += A[i][j]*x[j]; } } double
ddot(double* a, double* b){
double aux=0; for(int i=0;i<n;i++) aux+=a[i]*b[i]; return
aux;
} int main() { double **A, *x, *f, *h, *g;
A=new double*[n]; x=new double[n]; f=new double[n]; g=new
double[n]; h=new double[n];
long int tt=clock(); gradcon();
printf("%10f\n",(tt-clock())/CLOCK_PER_SEC);
return 0; }
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 12 /
118
Le même en C++ (II)
void gradcon(double** A, double* x, double* f, double* h, double*
g){
for(int i=0;i<n;i++){ A[i]=new double[n]; f[i]=i/double(n);
x[i]=i; for(int j=0;j<n;j++) A[i][j]=i*j/(n*n+11.);
} double normg2old = 1e10; for(int iter=0;iter<niter;iter++)
{
} }
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 13 /
118
L’outil linux ubuntu
Dans l’ensemble les pro du calcul travaillent sous unix: l’accès
aux bibliothèques y est plus simple. L’OS Mac est construit sur un
Berkeley unix. Donc pas la peine de mettre ubuntu. Sur PC le plus
simple est d’installer ubuntu avec wubi, une application windows
qui met ubuntu dans un dossier distinct et sans partitionner le
disque (donc pas de danger pour Windows). Réserver 12Go de disque
au moins.
Installer la 9.04 sur XP (9.10+XP=pb de veille) ou la 9.10 sur
vista/7. Ouvrir une fenêtre terminal dans ubuntu et taper g++ puis
faire ce qui est demandé (sudo install...) idem en tapant javac
(installer le jdk) idem en tapant mpicc (installer openmpi) idem en
tapant gnuplot (installer le gnuplot-x11) Télécharger avec le
firefox de ubuntu la version Galileo de Eclipse C++, de-zipper et
tester (voir plus bas).
Vous avez maintenant les outils pour le C++, l’openMP, le MPI.
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 14 /
118
L’environnement de travail Eclipse (I)
Eclipse est très populaire en entreprise. Pour tester un programme:
créer un projet par le menu file/new C++ project. Choisir Hello
world C++Project Nommer le projet; faire next plutot que
finish.
Puis cliquer sur le marteau puis sur la flèche blanche dans le rond
vert Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 15 /
118
L’environnement de travail Eclipse (II)
Multi plateforme et gratuit mais suppose que gcc et un java sont
déjà installés (peut nécessiter cygwin sous windows) Ecrit en java
et meme portable sur une clef USB Signale les erreurs de syntaxe
clairement Permet de profiter pleinement du debuggeur gdb Permet de
gérer des makefiles complexes (calcul // entre autre) Diminue le
temps de développement
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 16 /
118
Première séance de TD
Ecrire un gradient conjugué en C++ Le transformer avec les appels
BLAS Etudier les perfs en fonction de la taille n de A Installer
Eclipse et faire tourner votre programme par eclipse Résoudre −u” =
1 dans (0,1) avec u(0) = u(1) = 0 par Différences Finies et la
méthodes du gradient conjugué pour le système linéaire. tester le
programme de la diapo suivante.
Dans un premier temps on étudie l’implémentation LU Vous devriez
vous aperçevoir que cblas ne fait pas trop de différence. En fait
il faut aller à blas3 pour voir que là la réduction du temps CPU
est de l’ordre de 10, comme le montre l’exemple suivant. D’ou
l’idée de grouper les instructions par blocs pour faire des appels
à blas3. Si vous vous en sentez le courrage dans l’exo
précédent...
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 17 /
118
Test de BLAS3 (Juvigny)
#include <cblas.h> /* On inclue l’interface C du blas */
double A[3000000], B[6000000], C[2000000];
void assembleMat( int ni, int nj, double A[]){ int i,j; double
xnj=nj;
for (i=0; i<ni; i++) for (j=0; j<nj; j++) A[i*nj+j] =
((i+j)%nj)/xnj;
} void prodMat(int ni,int nj,int nk,double A[],double B[],double
C[]){ int i,j,k; /* Calcul produit matrice--vecteur (C assumed =0)
*/ for (i=0; i <ni; i++) for (k=0; k<nk; k++) for (j=0;
j<nj; j++) C[i*nk+k] += A[i*nj+j]*B[j*nk+k];
} int main(int nargc, char* argv[]){
const int ni = 1000, nj = 3000, nk = 2000; assembleMat( ni, nj, A);
assembleMat( nj, nk, B);
# ifdef USEBLAS
cblas_dgemm(CblasRowMajor,CblasNoTrans,CblasNoTrans,ni,nk,
nj, 1., A, nj, B, nk, 0., C, nk); # else
prodMat(ni,nj,nk,A,B,C);
# endif return 0;}
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 18 /
118
Outline I 1 Leçon 1 : Architecture des machines
Principes Les environnements de travail Machines Parallèles
2 Leçon 2: architectures parallèles Les logiciels Un exemple facile
a paralléliser Le code C
3 Leçon 3: Parallélisation avec openMP Principes de openMP Exemples
et syntaxes Analyse de edostochOMP.c Plus d’exemple et de mots clés
en OpenMP Exemple 2: EDP-1d en éléments finis Discretisation par
Elements Finis P1
Parallélisation en OpenMP Olivier Pironneau (LJLL) Optimisation des
performances et Parallélisme en C/C++ - openMP - MPI - UPC - CUDA
-openCLMPE 19 / 118
Outline II Le code vanilafem.c
4 Leçon 4: Message Passing Interface Historique et résumé
Parallélisation mémoire distribuée en MPI
5 Leçon 5: UPC: Unified Parallel C UPC de Berkeley
6 Leçon 6: Les GPU, CUDA et openCL Historique Portabilité: openCL
openCL sur Mac
7 Leçon 7: Les outils du calcul parallèle le partitionneur Metis
pour les Maillages non-structurées Integration les compilateurs
dans Eclipse Bibliothèques pour le calcul parallèle PetSc
8 Leçon 8: les algorithmes du calcul parallèle Olivier Pironneau
(LJLL) Optimisation des performances et Parallélisme en C/C++ -
openMP - MPI - UPC - CUDA -openCLMPE 20 / 118
Outline III Méthodes de Schwarz Méthode de Schur Méthodes
Lagrangienne et Mortier-Joint
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 21 /
118
Multiprocesseurs
Mémoires partagées Mémoires distribuées SIMD - MIMD Cartes mères
multi-cœurs et multi-processeurs GPU
float x[100], y[100], z[100]; for (i = 0; i < 100; i++) if (
y[i]!= 0) z[i] = x[i] / y[i]; else z[i]=y[i];
implementé en SIMD par
y[i]==0? do nothing y[i] !=0 do z[i] = x[i] / y[i]; y[i] !=0 do
nothing y[i] ==0 do z[i] = y[i];
De nombreux processeurs peuvent être inoccupés! Olivier Pironneau
(LJLL) Optimisation des performances et Parallélisme en C/C++ -
openMP - MPI - UPC - CUDA -openCLMPE 22 / 118
Ordinateurs en réseaux
Cluster = un système par carte mère + une connectique rapide
(myrinet, infiniband, ethernet gygabit) Ferme de stations:
typiquement = plusieurs PC en réseau par ethernet Grid: Typiquement
des machines sur la toile www. La grille EGEE permet d’accéder à 45
000 machines sur 240 sites
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 23 /
118
Les Ordinateurs disponibles
Vitesse en nb d’opérations flottantes par secondes (flops) (voir
www.top500.org)
machine Intel centrino 2 a 2 ghz: 15 giga flops core i7 de Intel:
nd il est seul. 4 coeurs mais de l’overclock (boost) sur un coeur
et avec un GPU Nvidia Tesla (128 proc) : 0.5 tera flops Carte mère
quadri-proc dual cores 3ghz: 80 Gflops Cluster 128 cartes bi-pro
dual core 3 ghz: 2 Tflops La machine js21 du ccre: 5 Tflops Le SX8
vectoriel de l’Idris: 60 Tflops L’ibm blue-gene de l’Idris: 140
Tflops Le Road-runner de Los-Alamos: 1 peta flops Le Jaguar (Cray
X86) de Oakridge Nat Lab: 1.74 Pflops
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 24 /
118
Les outils Middleware (intergiciels!)
openMP MPI (openMPI et MPICH2) Globus et mpich-G upc-Berkeley,
chapel CUDA, openCL
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 25 /
118
Exemple 1. Calcul d’une option en finance
Le sousjacent St est modélisé par une EDO-S
dSt = St (rdt + σdWt ), S(0) = S0
Le put est calculé par P0 = e−rT E(K − ST )+
La loi des grands nombres⇒ P0 ≈ e−rT
M (K − Si T )+
dtN (0,1),
N (0,1) = √ −2 log x cos(2πy) x,y aleatoires uniformes ∈
(0,1).
Le calcul des Si T est “embarrassingly parallel".
Voici le code C
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 26 /
118
edostoch.c(I)
#include <stdlib.h> // ... stdio, math et time.h
const int M=365; // nombre de pas de temps const double two_pi
=6.28318530718; double CPUtime(){ return ((double)
clock())/CLOCKS_PER_SEC;}
double gauss(){ double x,y; x= (1.+rand())/(1.+RAND_MAX); y=
(1.+rand())/(1.+RAND_MAX);
return sqrt( -2 *log(x) )*cos(two_pi*y); }
double EDOstoch(const double S0, const double dt, const double sdt,
const double rdt){
double S= S0; int i; for(i=1;i<M;i++)
S= S*(1.+gauss()*sdt+rdt); return S;
}
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 27 /
118
edostoch.c (II)
int main(int argc, char* argv[]){ const double K=110, S0=100; const
int kmax=20000; // nb de realisations const double T=1., r=0.03,
sigma=0.2; double dt=T/M, sdt, rdt, P0=0; double time0=CPUtime();
sdt =sigma*sqrt(dt); rdt = r*dt; srand(time(NULL));
for(int k=0; k<kmax;k++){ double Sa= EDOstoch(S0, dt, sdt, rdt);
if(K>Sa) P0 += K-Sa;
}
Exercice: En vue du parallélisme proposer une scission de la partie
qui prend du temps en 2 blocs indépendants.
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 28 /
118
Outline I 1 Leçon 1 : Architecture des machines
Principes Les environnements de travail Machines Parallèles
2 Leçon 2: architectures parallèles Les logiciels Un exemple facile
a paralléliser Le code C
3 Leçon 3: Parallélisation avec openMP Principes de openMP Exemples
et syntaxes Analyse de edostochOMP.c Plus d’exemple et de mots clés
en OpenMP Exemple 2: EDP-1d en éléments finis Discretisation par
Elements Finis P1
Parallélisation en OpenMP Olivier Pironneau (LJLL) Optimisation des
performances et Parallélisme en C/C++ - openMP - MPI - UPC - CUDA
-openCLMPE 29 / 118
Outline II Le code vanilafem.c
4 Leçon 4: Message Passing Interface Historique et résumé
Parallélisation mémoire distribuée en MPI
5 Leçon 5: UPC: Unified Parallel C UPC de Berkeley
6 Leçon 6: Les GPU, CUDA et openCL Historique Portabilité: openCL
openCL sur Mac
7 Leçon 7: Les outils du calcul parallèle le partitionneur Metis
pour les Maillages non-structurées Integration les compilateurs
dans Eclipse Bibliothèques pour le calcul parallèle PetSc
8 Leçon 8: les algorithmes du calcul parallèle Olivier Pironneau
(LJLL) Optimisation des performances et Parallélisme en C/C++ -
openMP - MPI - UPC - CUDA -openCLMPE 30 / 118
Outline III Méthodes de Schwarz Méthode de Schur Méthodes
Lagrangienne et Mortier-Joint
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 31 /
118
openMP
Historique: créé en 1991 on en est à la norme 2.5 de 2005
Implémentation cachée à l’utilisateur : integré à gcc 4.2 et plus
pour les systèmes qui implémentent la bibliothèque pthreads et
aussi a MS visual C++ 2.5 et plus Directives données au compilateur
sous forme de #pragma
C’est un modèle SIMD avec mémoire partagée ou à priori toutes les
variables sont globales.
Références: http://www.openmp.org/,
http://bisqwit.iki.fi/story/howto/openmp/,
http://en.wikipedia.org/wiki/OpenMP
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 32 /
118
Hello world
int main () { printf("Hello\n"); double
time0=omp_get_wtime();
#pragma omp parallel for num_threads(2) for(int n=0; n<10;
++n)
printf(" %d ",n); printf("CPUtime=%f\n",omp_get_wtime()-time0);
return 0;
}
Compiler avec g++ -fopenmp hellomp.c -o hello (peut demander export
PATH=/usr/local/bin:$PATH) resultat de ./hello: 0 5 1 6 2 7 3 8 4 9
CPUtime=0.000633 Si dans eclipse il faut changer
projet/properties/settings/linker
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 33 /
118
Principales commandes
#pragma omp parallel { ... } #pragma omp for #pragma omp parallel
sections { { Work1(); } #pragma omp section { Work2(); Work3(); }
#pragma omp section { Work4(); }
} #pragma omp barrier #pragma omp atomic counter += value; // only
one thread will do that int a, b=0;
#pragma omp parallel for private(a) shared(b)
chaque thread a son ‘a‘ mais ‘b‘ est le meme pour tous
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 34 /
118
Concepts
Reduction: fabriquer une seule variable a partir de plusieurs
variables private du meme nom; ex si une var A existe dans 2
processes une reduction+ des A rend une var globale a contenant la
somme des 2 A. Fonctions utiles
int thread_id = omp_get_thread_num(); int nthreads =
omp_get_num_threads(); DWORD_PTR mask = (1 <<
omp_get_thread_num()); SetThreadAffinityMask( GetCurrentThread(),
mask );
Un seul for par parallel bloc sera parallélisé. openMP est simple
mais sa scalabilité est limitée par le fait de la mémoire partagée.
Pour utiliser Eclipse il faut rajouter openmp dans le menu
projet/propriété/C-C++ setting/linker.
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 35 /
118
Loi de Amdhal
Loi de Amdhal: le speed-up est limité par la partie séquentiel du
programme. Le speed-up est S/[(1-p)S+pS/N] ou S est le temps calcul
sequentiel,p la proportion parallélisée et N le nb de
processeurs.
Exercice: Obtenir le meilleur speed-up avec openMP sur
edostoch.c
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 36 /
118
edostochOMP.c I
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 37 /
118
edostochOMP.c II
L’exemple suivant va permettre de comparer les performances de
openMP comparé à CBLAS présenté plus haut pour le produit matrice
vecteur.
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 38 /
118
Produit Matrice Vecteur (Juvigny) I
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 39 /
118
Produit Matrice Vecteur (Juvigny) II
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 40 /
118
Produit Matrice Vecteur (Juvigny) III
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 41 /
118
Exercices pour le TD
1 Lancer edostochomp.c et étudier les perfs en fonctions de P 2
Changer S[] en une seule variable et utiliser reduce; il
faudra
aussi utiliser la fonction rand_r(state) qui, elle, est réentrante.
3 Lancer prog2.c pour comparer openMP et BLAS 4 Modifier le code
pour utiliser openMP ET cblas. 5 Mettre des directives openMP dans
le prgramme vanilafem.c
çi-dessous.
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 42 /
118
Equation de la chaleur
∂tu − ∂x (κ∂xu) = f , u(0, t) = u(L, t) = 0, u(x ,0) = u0(x) ∀x , t
∈ (0,L)× (0,T )
Formulation variationnelle et differences finies en temps∫ L
0
∫ L
0 (0,L)
Discretisation en espace par éléments finis de degrés 1: on
remplace V par Vh, l’espace des fonctions continues affines par
morceaux sur [0,L] = ∪i [xi , xi+1] avec xi = ih,i=0..I-1, tel que
Ih = L. On obtient un système lineaire a chaque itération pour Um+1
∈ RN :
B(Um+1 − Um) + AUm+1 = F ∈ RN ,
avec Bij = 1 δt
∫ L
0 κ∇w i∇w jdx
où w i est la fonction de Vh qui vaut δij en xj . Olivier Pironneau
(LJLL) Optimisation des performances et Parallélisme en C/C++ -
openMP - MPI - UPC - CUDA -openCLMPE 43 / 118
Equation de la chaleur: discretisation
Il est facile de voir que A et B sont tridiagonales avec
Bii = 2h δt , Bi,i−1 = Bi,i+1 =
h δt , Aii =
h
A priori le système tridiagonal pourUm+1 is résolu par
factorisation de Gauss (A = LU) . La parallélisation de la méthode
du gradient conjugé est beaucoup plus simple mais dans un premier
temps on étudie l’implémentation LU. Ci dessous le programme pour
Black-Scholes:
∂tu + ru − rx∂xu − σ2x2
2 ∂xxu = 0, u(t = 0) = max(K − x ,0)
If there is a low-barrier then u = 0 at xm; u = 0 at xM anyway but
if xM is not large compare to K then it is an up-barrier.
L’exercice va consister à mettre des directives openMP dans le
code, essentiellement en parallélisant toutes les boucles
for.
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 44 /
118
Le code vanilafem.c (I)
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 45 /
118
Le code vanilafem.c (II)
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 46 /
118
Le code vanilafem.c (III)
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 47 /
118
Le code vanilafem.c (IV)
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 48 /
118
Le code vanilafem.c (V)
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 49 /
118
Outline I 1 Leçon 1 : Architecture des machines
Principes Les environnements de travail Machines Parallèles
2 Leçon 2: architectures parallèles Les logiciels Un exemple facile
a paralléliser Le code C
3 Leçon 3: Parallélisation avec openMP Principes de openMP Exemples
et syntaxes Analyse de edostochOMP.c Plus d’exemple et de mots clés
en OpenMP Exemple 2: EDP-1d en éléments finis Discretisation par
Elements Finis P1
Parallélisation en OpenMP Olivier Pironneau (LJLL) Optimisation des
performances et Parallélisme en C/C++ - openMP - MPI - UPC - CUDA
-openCLMPE 50 / 118
Outline II Le code vanilafem.c
4 Leçon 4: Message Passing Interface Historique et résumé
Parallélisation mémoire distribuée en MPI
5 Leçon 5: UPC: Unified Parallel C UPC de Berkeley
6 Leçon 6: Les GPU, CUDA et openCL Historique Portabilité: openCL
openCL sur Mac
7 Leçon 7: Les outils du calcul parallèle le partitionneur Metis
pour les Maillages non-structurées Integration les compilateurs
dans Eclipse Bibliothèques pour le calcul parallèle PetSc
8 Leçon 8: les algorithmes du calcul parallèle Olivier Pironneau
(LJLL) Optimisation des performances et Parallélisme en C/C++ -
openMP - MPI - UPC - CUDA -openCLMPE 51 / 118
Outline III Méthodes de Schwarz Méthode de Schur Méthodes
Lagrangienne et Mortier-Joint
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 52 /
118
Présentation de MPI
Après beaucoup de propositions architecture-dépendantes, les
programmeurs plébicitent PVM de J. Dongarra, puis sur le même
modèle un concorsium produit en 1994: MPI.
MPI est fondamentalement multiple instruction - multiple data -
distributed memory mais de manière naturel chaque proc exécute le
même programme; sinon il faut spécifier que le proc p exécute le
prog p. la communiction des données est à la charge du programmeur,
ce qui complique fortement la programmation mais permet de bien
voir comment optimiser l’implémentation. Apres MPI_init() et
jusqu’a MPI_finalize() chaque proc recoit le programme et une copie
des data. Une variable se retrouve donc stockée P fois sauf si elle
est déclarée en interne du prog du proc p.
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 53 /
118
Le Hello World de MPI
se compile (mpic++ OK aussi) et donne :
% mpicc hello.c -o hello % mpirun -np 2 hello Proc 1 received:
Hello there from proc 0
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 54 /
118
Produit matrice vecteur
On exploite le fait que A est tridiagonal: si {xi}iM−1
im est dans un banc mémoire p Axi = aixi−1 + bixi + cixi+1 demande
la reception de xim−1 et de xiM des bancs mémoires p − 1 et p +
1.
void Option::atimesx(Vector& a, Vector& b, Vector& c,
Vector& x,Vector& Ax) { MPI_Status s; if(p!=0){
MPI_Send(&(x[im]),1,MPI_DOUBLE, p-1, 0, MPI_COMM_WORLD);
MPI_Recv(&(x[im-1]),1,MPI_DOUBLE,p-1,0,MPI_COMM_WORLD,&s);
} if(p!=P-1){ MPI_Send(&(x[iM-1]),1,MPI_DOUBLE, p+1, 0,
MPI_COMM_WORLD);
MPI_Recv(&(x[iM]),1,MPI_DOUBLE,p+1,0,MPI_COMM_WORLD,&s);
} for(int i=im1;i<iM1;i++)
Ax[i] = a[i]*x[i-1]+b[i]*x[i]+c[i]*x[i+1]; }
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 55 /
118
Produit scalaire
Chaque proc fait sa part de boucle puis les resultats sont
aditionnés dans le proc 0 et le résultat est renvoyé a tous les
procs.
}
Noter que la mémoire n’est pas optimisée et qu’il faudrait decaller
les indices et accéder à v [i − im1].
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 56 /
118
La fonction principale (I) Le C++ de la fonction qui calcul
l’option:
void Option::calc() { const double dt=m.T/m.nT; int argc; char
**argv; MPI_Status status; MPI_Init (&argc, &argv); /*
starts MPI */ MPI_Comm_rank (MPI_COMM_WORLD, &p); /* get
current process id */ MPI_Comm_size (MPI_COMM_WORLD, &P); /*
get number of processes */ im=(m.nX*p)/P, iM = (m.nX*(p+1))/P; im1
= (im==0)?1:im, iM1 = (iM==m.nX)?m.nX-1:iM;
for (int i=im1; i<iM1; i++) { double hi = m.x[i]-m.x[i-1], hi1 =
m.x[i+1]-m.x[i]; double xss = m.x[i]*sigma*sigma; // FEM tridiag
matrix: bm[i] =(hi+hi1)*(1./3 +dt*(m.x[i]*xss/hi/hi1+r)/2); am[i] =
hi/6 - dt*m.x[i]*(xss/hi - r)/2; cm[i] = hi1/6- dt*m.x[i]*(xss/hi1
+ r)/2; } for (int i=im; i<iM; i++) uold[i] = u0(m.x[i]);
MPI_Barrier(MPI_COMM_WORLD);
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 57 /
118
La fonction principale (II)
for (int j=1; j<m.nT; j++) { \\ time loop if(p!=0){
MPI_Send(&(uold[im]),1,MPI_DOUBLE, p-1,0, MPI_COMM_WORLD);
MPI_Recv(&(uold[im-1]),1,MPI_DOUBLE,p-1,0,MPI_COMM_WORLD,&s);
} if(p!=P-1){
MPI_Send(&(uold[iM-1]),1,MPI_DOUBLE, p+1,0, MPI_COMM_WORLD);
MPI_Recv(&(uold[iM]),1,MPI_DOUBLE,p+1,0,MPI_COMM_WORLD,&s);
} for (int i=im1; i<iM1; i++) { double hi = m.x[i]-m.x[i-1], hi1
= m.x[i+1]-m.x[i];
w[i]=(hi+hi1)*uold[i]/3+(hi*uold[i-1]+hi1*uold[i+1])/6; }
u[m.nX-1]=0; u[0]=uold[0]*exp(-r*dt); // C.L. double h1 =
m.x[1]-m.x[0];
w[1]-=uold[0]*(h1/6-dt*m.x[1]*(m.x[1]*sigma*sigma/h1-r)/2);
MPI_Barrier(MPI_COMM_WORLD); gradconj(am,bm,cm,w); for (int i=im1;
i<iM1; i++) uold[i]=w[i]; } MPI_Finalize(); }
Note: la récupération des résultats doit se faire par un MPI_Send
bloc. Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 58 /
118
Outline I 1 Leçon 1 : Architecture des machines
Principes Les environnements de travail Machines Parallèles
2 Leçon 2: architectures parallèles Les logiciels Un exemple facile
a paralléliser Le code C
3 Leçon 3: Parallélisation avec openMP Principes de openMP Exemples
et syntaxes Analyse de edostochOMP.c Plus d’exemple et de mots clés
en OpenMP Exemple 2: EDP-1d en éléments finis Discretisation par
Elements Finis P1
Parallélisation en OpenMP Olivier Pironneau (LJLL) Optimisation des
performances et Parallélisme en C/C++ - openMP - MPI - UPC - CUDA
-openCLMPE 59 / 118
Outline II Le code vanilafem.c
4 Leçon 4: Message Passing Interface Historique et résumé
Parallélisation mémoire distribuée en MPI
5 Leçon 5: UPC: Unified Parallel C UPC de Berkeley
6 Leçon 6: Les GPU, CUDA et openCL Historique Portabilité: openCL
openCL sur Mac
7 Leçon 7: Les outils du calcul parallèle le partitionneur Metis
pour les Maillages non-structurées Integration les compilateurs
dans Eclipse Bibliothèques pour le calcul parallèle PetSc
8 Leçon 8: les algorithmes du calcul parallèle Olivier Pironneau
(LJLL) Optimisation des performances et Parallélisme en C/C++ -
openMP - MPI - UPC - CUDA -openCLMPE 60 / 118
Outline III Méthodes de Schwarz Méthode de Schur Méthodes
Lagrangienne et Mortier-Joint
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 61 /
118
Présentation de UPC
Proposé en 1999, UPC est dévelopé par un consortium dont Berkeley
fait partie. Berkeley Unified Parallel C compiler tourne sur les
principaux environnements. La compilation et l’exécution se font
par:
upcc -pthreads hello.upc -o hello upcrun -n 2 ./hello
Il reprend des idées de MPI mais simplifie enormément les
communications en introduisant la notion de shared variable.
L’installation de UPC est relativement facile sur un Mac-Intel,
possible sur un PC linux, difficile sur un PC-Windows, le plus
simple etant pour ce dernier d’installer un cygwin special
contenant la librairie pthreads et dispo sur le site UPC-Berkeley.
Ce type de langage dit PGAS, est un sujet de recherche important.
Il existe d’autres tentatives comme Church de CRAY research et
CAF/Fortran ainsi que Titanium/Java.
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 62 /
118
Organisation mémoire
Le programme est recopié dans chaque proc, chaque variable est en
THREADS exemplaires sauf si elle est déclarée shared; dans ce ca
elle est par defaut sur la mémoire du process 0. Les shared array
sont distribués:
#define N 1000 int i; shared double x, y[N] shared [2] double
a[N];
Chaque proc accède a toute variable shared et connait son affinity.
Si THREADS=10, il y aura 10 instances de i, une seule de x et dans
Thread0, une seule de chaque y[i] mais y[0] dans Thread0...y[9]
dans Threads9, y[10] dans Thread0... a[0],a[1] sera dans Thread0,
a[2],a[3] dans Thread1...
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 63 /
118
Exemple: addition de 2 vecteurs (I)
#define J 200000 #define N J*THREADS
shared double a[N], b[N]; shared double sum;
int main(){ int j; double localSum=0; for(j=0;j<J;j++){ a[j] =1;
b[j] =1e-8;} // initialisation for(j=0;j<J;j++)
localSum += a[j] + b[j] ; sum += localSum; // not scalable
upc_barrier; if(MYTHREAD==0)
printf("sum = %f \n", sum); return 0;
}
Mais ce programme n’est pas scalable. Olivier Pironneau (LJLL)
Optimisation des performances et Parallélisme en C/C++ - openMP -
MPI - UPC - CUDA -openCLMPE 64 / 118
Exemple: addition de 2 vecteurs (II) On peut utiliser une fonction
de la bibliothèque bupc
#include <bupc_collectivev.h> #define J 200000 #define N
J*THREADS
shared double a[N], b[N];
int main(){ int j; double localSum=0; for(j=0;j<J;j++){ a[j] =1;
b[j] =1e-8;} // initialisation for(j=0;j<J;j++)
localSum += a[j] + b[j] ; upc_barrier; double sum =
bupc_allv_reduce(double, localSum, 0, UPC_ADD);
if(MYTHREAD==0)
printf("sum = %f \n", sum ); return 0;
}
Remarque: les perfs ne sont pas au rendez-vous! Olivier Pironneau
(LJLL) Optimisation des performances et Parallélisme en C/C++ -
openMP - MPI - UPC - CUDA -openCLMPE 65 / 118
Exemple: addition de 2 vecteurs (III)
#include <bupc_collectivev.h> #define J 100000 #define N
J*THREADS
shared double a[N], b[N]; int main(){ int j; double
localSum=0;
// initialisation de a et b ici upc_forall(j=0;j<N;j++;j)
}
Le upc_forall est un “parallel for” où le dernier argument indique
qui fera l’opération. Ici l’affinité de i détermine le proc: comme
i est local, c’est lorsque le i de la boucle est egal au i local.
On aurait pu écrire: for(i=0;i<N;i++)
if(MYTHREAD==(i%THREADS)) localSum += a[j] + b[j] ;
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 66 /
118
Mesure du temps calcul
#include <sys/time.h> // file somme.upc shared double
runtimes[THREADS]; ... int main(){
struct timeval ts_st, ts_end; gettimeofday( &ts_st, NULL
);
... // the tasks e.g localSum += log(sin(a[j]))+cos(exp(b[j])) ;
gettimeofday( &ts_end, NULL ); runtimes[MYTHREAD] =
ts_end.tv_sec-ts_st.tv_sec
+ (ts_end.tv_usec - ts_st.tv_usec) / 1000000.0;
if(MYTHREAD==0){
max_time = runtimes[0]; for( i=1; i<THREADS; i++ )
if( max_time < runtimes[i] ) max_time = runtimes[i];
printf("CPUtime=%f ", max_time);
} return 0; }
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 67 /
118
Exemple: edostch.upc
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 68 /
118
Locks
upc_lock(L); PT += S; upc_unlock(L); ... upc_lock_free(L);
}
Pour éviter que 2 process écrire PT exactement en même temps on
utilise un lock. Toutefois si PT est déclaré en strict shared
double alors les locks ne sont pas nécéssaires. UPC est une
direction pour l’avenir mais les compilo ne sont ni C++ ni
optimisés comme gcc
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 69 /
118
Exemple:vanilafem.upc (I)
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 70 /
118
Exemple: vanilafem.upc (II)
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 71 /
118
Exemple 2(0): vanilafem.upc
• L’ implémentation par sous domaine ci-dessous n’améliore pas •
UPC ne gère pas le C++ • Les "shared array" sont globaux (alloc
dynamique possible) • Utilisation des locks ralentit terriblement •
Le break sur un process dans le gradconj: que faire de l’autre? •
Performences très inégales: ici n=1: 0.89", n=2: 0.59" • Les
compilateurs n’étant pas optimisés il est très difficile de battre
gcc
Method gcc g++ OMP mpicc(2p) mpic++(2p) upc(2p) clock() 0.04 0.017
1.8 0.19 0.65 0.59 full time 0.04 0.017 1.8 1.8 0.7 3.0
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 72 /
118
Exemple 2(I): vanilafem2.upc
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 73 /
118
Exemple 2(II): vanilafem2.upc
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 74 /
118
Exemple 2(III): vanilafem2.upc
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 75 /
118
Exemple 2(IV): vanilafem2.upc
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 76 /
118
Exemple 2(V): vanilafem2.upc
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 77 /
118
Exemple 2(V): vanilafem2.upc
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 78 /
118
Exercices pour le TD
1 Lancer edostoch.upc et étudier les perfs en fonctions du nombre
de proc
2 Vérifier que le programme vanilafem0.upc çi-dessus tourne sur 1
proc et pas sur plus et chercher à comprendre pourquoi.
3 Mettre des directives UPC dans la fonction gradconj du programme
vanilafem0.upc pour obtenir de bonnes perfs et des résultats justes
en multi-proc.
4 Etudier les perf en fonction du nombre de proc
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 79 /
118
Outline I 1 Leçon 1 : Architecture des machines
Principes Les environnements de travail Machines Parallèles
2 Leçon 2: architectures parallèles Les logiciels Un exemple facile
a paralléliser Le code C
3 Leçon 3: Parallélisation avec openMP Principes de openMP Exemples
et syntaxes Analyse de edostochOMP.c Plus d’exemple et de mots clés
en OpenMP Exemple 2: EDP-1d en éléments finis Discretisation par
Elements Finis P1
Parallélisation en OpenMP Olivier Pironneau (LJLL) Optimisation des
performances et Parallélisme en C/C++ - openMP - MPI - UPC - CUDA
-openCLMPE 80 / 118
Outline II Le code vanilafem.c
4 Leçon 4: Message Passing Interface Historique et résumé
Parallélisation mémoire distribuée en MPI
5 Leçon 5: UPC: Unified Parallel C UPC de Berkeley
6 Leçon 6: Les GPU, CUDA et openCL Historique Portabilité: openCL
openCL sur Mac
7 Leçon 7: Les outils du calcul parallèle le partitionneur Metis
pour les Maillages non-structurées Integration les compilateurs
dans Eclipse Bibliothèques pour le calcul parallèle PetSc
8 Leçon 8: les algorithmes du calcul parallèle Olivier Pironneau
(LJLL) Optimisation des performances et Parallélisme en C/C++ -
openMP - MPI - UPC - CUDA -openCLMPE 81 / 118
Outline III Méthodes de Schwarz Méthode de Schur Méthodes
Lagrangienne et Mortier-Joint
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 82 /
118
Graphic Processor Units
• Le marché du jeu video à induit une concurrence féroce entre les
2 grands constructeurs ATI et Nvidia. • Le besoin de réalisme a
obligé les concepteurs de jeux à revenir vers les équations
fondamentales de la physique pour la simulation, en particulier
pour l’eau et la fumée. • Vers 2006 les unités de calcul
élémentaires sont devenues capables de calculer en virgule
flottante: le GPGPU (general purpose graphic processor unit). • Des
chercheurs comme Pat Hanrahan et Ian Buck (Stanford) ont développé
des langages dédiés comme brook, puis CUDA; le langage OpenCL est
un travail d’équipe (consortium Khronos). • Intel nous prommet avec
Larrabee un processeurs sur le principe des GPGPU: 32 CPU avec des
mémoires hiérarchiques et des communications rapides.
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 83 /
118
Comparaison de performance sur edostoch.c
nb threads omp gcc4.4 MPI UPC CUDA CPU - GPU 1 0.9489 1.1388 2
0.5647 0.5150 0.5805 8 0.1547
10 0.1316 16 0.1412 32 0.0207 0.1602
CBLAS sur edpplain.cpp clock count= 8242 sans optim clock count=
7363 avec -O3 sans CBLAS clock count= 3690 avec O3 et CBLAS
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 84 /
118
Le Modèle de mémoires de Nvidia (I)
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 85 /
118
Le Modèle de mémoires de Nvidia (II)
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 86 /
118
Le Modèle de mémoires de Nvidia (III)
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 87 /
118
Programmation en CUDA
Nous allons ecrire un priceur d’option put basé sur la
formule
Sn T = S0e(r− 1
N∑ n=1
(K − Sn T )+
Cette formule vient d’une solution analytique de l’EDS de
Black-Scholes pour St lorsque r et σ sont constants. Nous allons
utiliser la formule de Cox-Muller pour générer les réalisations Nn
de la variable aléatoire gaussienne N :
N(0,1) = √ −2 log(x) cos(2πy), x , y aleatoires uniformes sur
(0,1)
• xn, yn sont générées par random() dans le CPU et • envoyées au
GPU en recopiant deux tableaux A1,A2 en RAM dans B1,B2, memoires de
la carte graphique. • Les 2 formules ci-dessous sont évaluées dans
le GPU pour chaque xn, yn de B1,B2 et • le resultat est stocké dans
B2 et renvoyé par recopié dans A2.
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 88 /
118
Edition-compilation-exécution
Le plus simple est d’utiliser un Mac avec une carte Nvidia. On peut
utiliser Xcode et meme Eclipse mais le plus simple est d’utiliser
une fenetre terminal.
Le site de Nvidia permet d’installer un binary tout pret dans
/usr/local/bin
Pour pointer sur le compilateur il faut faire export
PATH=/usr/local/cuda/bin:$PATH export DYLD_LIBRARY_PATH
=/usr/local/cuda/lib:$DYLD_LIBRARY_PATH
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 89 /
118
Implémentation des formules (cf. BSCuda.cu)
BSgpu et BScpu appelle BS sur chaque éléments des tableaux.
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 90 /
118
Transfer du CPU au GPU
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 91 /
118
Calcul dans le GPU
Exécute BSgpu sur Nthreads=512 chacun prenant en charge Nblocks=256
et copie les résultats dans A2
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 92 /
118
Portage de vanilafem.c sous CUDA avec cublas
Preambule Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 93 /
118
Multiplication Matrice Vector (cf. testcublas.cu)
Utilisation de cblas
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 94 /
118
Préparation de l’appel d’une fonction cublas
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 95 /
118
Appel de la fonction de cublas
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 96 /
118
Gradient Conjugué cublas
Malheureusement les perfs ne sont pas au rendez-vous,
essentiellement parce que ce qui est en dehors de cublas se fait
dans le CPU et implique des communications non gérées.
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 97 /
118
La méthode de Jacobi
En différences finies le probleme −u” = 1, u(0) = u(1) = 0 devient
Au = 1 ou A est une matrice tridiagonale d’éléments (−1,2,−1)h−2,
où h est la taille du maillage. Jacobi, c’est itérer sur
l’équation:
vi = (ui + 1 + ui−1 + h2)/2, ∀i puis ui = vi ∀i
Gauss-Seidel rouge noir, cela consiste a faire
ui = (ui+1 + ui−1 + h2)/2, ∀i pairs puis pour tout i impair ui =
(ui+1 + ui−1 + h2)/2
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 98 /
118
Programmation en CUDA de la méthode de Jacobi (I)
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 99 /
118
Programmation en CUDA de la méthode de Jacobi (II)
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 100 /
118
openCL sur Mac OSX 10.6
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 101 /
118
HMPP et CAPS Entreprise
Traduction automatique en CUDA, openCL... Utiliser le concept de
codelets: "Codelet=function with no return and arguments which are
const input" Ainsi peut on faire tourner le codelet sur n’importe
quel proc.
Apple propose un concept similaire : le block (proposé au C++
standard). C’est la généralisation du pointeur sur une fonction.
Exemple:
FILE *fp = fopen(filename, "r"); if (fp == NULL) { perror("Unable
to open file");} else {} char line[MAX_LINE]; while (fgets(line,
MAX_LINE, fp)) {work; work; work;} fclose(fp); ... remplacer~ par
foreach_line(filename, ^(char* line) {work; work;});
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 102 /
118
Exercices pour le TD sur CUDA
Faire tourner BScuda.cu et évaluer les performances en changeant la
tailles des blocs Faire tourner jacobi.cu et comparer avec gauss.cu
Faire tourner vanilaFEMcuBLAS.cu remplacer le gradient conjugué par
un jacobi item Evaluer les perfs de vanilaFEMcuBLAS avec CG et avec
jacobi.
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 103 /
118
Outline I 1 Leçon 1 : Architecture des machines
Principes Les environnements de travail Machines Parallèles
2 Leçon 2: architectures parallèles Les logiciels Un exemple facile
a paralléliser Le code C
3 Leçon 3: Parallélisation avec openMP Principes de openMP Exemples
et syntaxes Analyse de edostochOMP.c Plus d’exemple et de mots clés
en OpenMP Exemple 2: EDP-1d en éléments finis Discretisation par
Elements Finis P1
Parallélisation en OpenMP Olivier Pironneau (LJLL) Optimisation des
performances et Parallélisme en C/C++ - openMP - MPI - UPC - CUDA
-openCLMPE 104 / 118
Outline II Le code vanilafem.c
4 Leçon 4: Message Passing Interface Historique et résumé
Parallélisation mémoire distribuée en MPI
5 Leçon 5: UPC: Unified Parallel C UPC de Berkeley
6 Leçon 6: Les GPU, CUDA et openCL Historique Portabilité: openCL
openCL sur Mac
7 Leçon 7: Les outils du calcul parallèle le partitionneur Metis
pour les Maillages non-structurées Integration les compilateurs
dans Eclipse Bibliothèques pour le calcul parallèle PetSc
8 Leçon 8: les algorithmes du calcul parallèle Olivier Pironneau
(LJLL) Optimisation des performances et Parallélisme en C/C++ -
openMP - MPI - UPC - CUDA -openCLMPE 105 / 118
Outline III Méthodes de Schwarz Méthode de Schur Méthodes
Lagrangienne et Mortier-Joint
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 106 /
118
Metis pour les methodes de sous domaine
La bibliothèque METIS permet de partitionner un maillage en N
partie. Il suffit de l’installer à partir du site
www-users.cs.umn.edu/∼karypis/metis/metis/download.html et
d’invoquer la fonction partmesh, par exemple ./partmesh
simpletest.txt 2 avec simpletest =
6 1 1 2 3 2 4 6 2 6 3 4 5 6 5 6 3 7 4 2 . 1
3
5
6
4
7
2
Le programme fournit en sortie deux fichiers de nom
simpletest.txt.epart.2 et simpletest.txt.npart.2
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 107 /
118
Metis: contenu des fichiers simpletest.txt
0BBBBBBBBBB@
epart npart 0 0 0 0 1 1 1 0 1 1 0 1
0
3
5
6
4
7
2
Le fichier simpletest.txt contient le nombre d’element et un entier
pour donner le type d’element (ici 1=triangles). Ensuite pour
chaque ligne il y a les 3 sommets du triangle correspondant a la
ligne. En sortie le fichier .npart.2 contient l’indice
d’appartenance des sommets aux sous domaines Ainsi le sommet 2 et
sur le sous-domaine de numero 0 alors que le sommet 2 appartient au
sous domaine 1. De meme le fichier .epart.2 donne les appartenances
des triangles aux sous-domaines et donc le triangle 3 appartient au
sous-domaine 1.
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 108 /
118
Eclipse et le calcul parallèle
Il faut installer les plug-ins PTP (Parallel Tools Plateform)
http://www.eclipse.org/ptp/docs/install.html (bien lire la doc)
openMP est dans gcc> 4.2, c.f. le plugin PTP openMPI 1.2 est
géré par eclipse/PTP mais il faut l’installer (configure, make
install, pas simple, marche pas sous cygwin) Un plug-in UPC peut
etre downloader pour PTP
http://wiki.eclipse.org/PTP/other_tools_setup
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 109 /
118
PetSc
- Présentation - Application a une méthode de sous-domaine avec
gradient conjugué - Une méthode de Scharwz
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 110 /
118
Outline I 1 Leçon 1 : Architecture des machines
Principes Les environnements de travail Machines Parallèles
2 Leçon 2: architectures parallèles Les logiciels Un exemple facile
a paralléliser Le code C
3 Leçon 3: Parallélisation avec openMP Principes de openMP Exemples
et syntaxes Analyse de edostochOMP.c Plus d’exemple et de mots clés
en OpenMP Exemple 2: EDP-1d en éléments finis Discretisation par
Elements Finis P1
Parallélisation en OpenMP Olivier Pironneau (LJLL) Optimisation des
performances et Parallélisme en C/C++ - openMP - MPI - UPC - CUDA
-openCLMPE 111 / 118
Outline II Le code vanilafem.c
4 Leçon 4: Message Passing Interface Historique et résumé
Parallélisation mémoire distribuée en MPI
5 Leçon 5: UPC: Unified Parallel C UPC de Berkeley
6 Leçon 6: Les GPU, CUDA et openCL Historique Portabilité: openCL
openCL sur Mac
7 Leçon 7: Les outils du calcul parallèle le partitionneur Metis
pour les Maillages non-structurées Integration les compilateurs
dans Eclipse Bibliothèques pour le calcul parallèle PetSc
8 Leçon 8: les algorithmes du calcul parallèle Olivier Pironneau
(LJLL) Optimisation des performances et Parallélisme en C/C++ -
openMP - MPI - UPC - CUDA -openCLMPE 112 / 118
Outline III Méthodes de Schwarz Méthode de Schur Méthodes
Lagrangienne et Mortier-Joint
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 113 /
118
Méthode de Schwarz avec recouvrement
On décompose = 1 ∪ 2 avec 1 ∩ 2 6= ∅: 1 Tant que |uk
1 − uk 2 |1∩2 > ε,
2 calculer uk+1 1 solution de l’EDP dans 1 avec uk+1
1 = uk 2 sur Γ12
3 calculer uk+1 2 solution de l’EDP dans 2 avec uk+1
2 = uk 1 sur Γ21
4 dans 1 ∩ 2 set uk+1 = 1 2 [uk+1
1 + uk+1 2 ].
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 114 /
118
Méthode de Schwarz sans recouvrement
1 Tant que |uk 1 − uk
2 |1∩2 > ε,
2 calculer uk+1 1 solution de l’EDP dans 1 avec uk+1
1 = λk on Γ12; 3 calculer uk+1
2 solution de l’EDP dans 2 avec uk+1 2 = λk on Γ21;
4 Poser λk+1 = λk + θ[∂uk+1
∂n ].
Exercice Prendre = (0,1) et trouver le bon signe et la meilleure
formule pour θ.
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 115 /
118
Méthode de Schur
Considerons le probleme d’algebre linéaire avec A ∈ Rn×n,b ∈
Rn:
Trouver x ∈ Rn tel que Ax = b
Soit une partition de A en 4 blocks A11 ∈ Rl×l , A12 ∈ Rl×(n−l),
A21 ∈ R(n−l)×l et A22 ∈ R(n−l)×(n−l) tel que:
A =
) .
Soit b1le vecteur des l premiere entrées de b et b2 le reste et de
même pour x . On a:(
A11 A12
A21 A22
−1 (b1 − A12x2), et
b1
La matrice A22 − A21(A11) −1A12 est le complément de Schur de
A.
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 116 /
118
Une Méthode lagrangienne (I) Principe
−u = f in , u|Γ = 0
et une partition sans recouvrement: = 1 ∪ 2, Σ = 1 ∩ 2, 1 ∩ 2 = ∅.
Soit
−ui = f in i , ui |Γ = 0, ∂ui
∂n |Σ = λ,
où nest une normale de Σ et où λ sera ajusté pour avoir u1 = u2 sur
Σ. Tout ceci se est équivalent à trouver {u1,u2, λ} ∈ H1(1)× H1(2)×
L2(Σ) tel sque∫
i ∇ui · ∇w dx + (−1)i ∫
Σ λw = ∫
0 (), i = 1,2,∫ Σ(u2 − u1)µ = 0, ∀µ ∈ L2(Σ).
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 117 /
118
Implémentation
Prenons des éléments finis de degré 1 pour u et 0 pour λ: Trouver
uh ∈ H0h et λh ∈ Lh tels que∫
hi ∇ui
∫ hi
0 A22 B2
B1T B2T 0
.
On note w i ∈ Hh et w i ∈ L2(Σ) les fonctions de base des 2
espaces, U i les componsantes de ui
j et Λ = ((λk )). Alors
Akk ij =
∫ Σh
w iw j , k = 1,2.
La méthode de Schur est bien adaptée pour construire un système
linéaire en Λ par élimination de U.
Olivier Pironneau (LJLL) Optimisation des performances et
Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCLMPE 118 /
118
Leçon 1 : Architecture des machines
Principes
Le code C
Principes de openMP
Exemples et syntaxes
Analyse de edostochOMP.c
Exemple 2: EDP-1d en éléments finis
Discretisation par Elements Finis P1
Parallélisation en OpenMP
Le code vanilafem.c
Historique et résumé
Leçon 5: UPC: Unified Parallel C
UPC de Berkeley
Historique
Integration les compilateurs dans Eclipse
Bibliothèques pour le calcul parallèle
PetSc
Méthodes de Schwarz
Méthode de Schur