• Aucun résultat trouvé

Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC - CUDA 1 / 118-op

N/A
N/A
Protected

Academic year: 2022

Partager "Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC - CUDA 1 / 118-op"

Copied!
118
0
0

Texte intégral

(1)

Optimisation des performances et Parallélisme en C/C++ - openMP - MPI - UPC - CUDA -openCL

http://www.ann.jussieu.fr/pironneau

Olivier Pironneau1

1University of Paris VI, Laboratoire J.-L. Lions,Olivier.Pironneau@upmc.fr

Cours Mastère 2, Automne 2009

(2)

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 FinisP1 Parallélisation en OpenMP

(3)

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

(4)

Outline III

Méthodes de Schwarz Méthode de Schur

Méthodes Lagrangienne et Mortier-Joint

(5)

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 dubusentre 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".

(6)

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.

(7)

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.

(8)

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];

(9)

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 fonctioncblas_daxpy(..) qui remplacey parαx+y.

Rappel: le gradient conjugué pour Ax=f (ou A estn×nsymmétrique) for (n=0;n<N;n+ +){

gn=Axn−f γ = |gn|2

|gn−1|2 hn=γhn−1−gn ρ= hn·gn

hn·Ahn xn=xn−1+ρhn }

(10)

CBLAS memento

Level1BLAS

dim scalar vector vector scalars 5-element array prexes

SUBROUTINE xROTG ( A, B, C, S ) Generate plane rotation S, D

SUBROUTINE xROTMG( D1, D2, A, B, PARAM ) Generate modied plane rotation S, D

SUBROUTINE xROT ( N, X, INCX, Y, INCY, C, S ) Apply plane rotation S, D

SUBROUTINE xROTM ( N, X, INCX, Y, INCY, PARAM ) Apply modied plane rotation S, D

SUBROUTINE xSWAP ( N, X, INCX, Y, INCY ) x$y S, D, C, Z

SUBROUTINE xSCAL ( N, ALPHA, X, INCX ) x x S, D, C, Z, CS, ZD

SUBROUTINE xCOPY ( N, X, INCX, Y, INCY ) y x S, D, C, Z

SUBROUTINE xAXPY ( N, ALPHA, X, INCX, Y, INCY ) y x + y S, D, C, Z

FUNCTION xDOT ( N, X, INCX, Y, INCY ) dot xTy S, D, DS

FUNCTION xDOTU ( N, X, INCX, Y, INCY ) dot xTy C, Z

FUNCTION xDOTC ( N, X, INCX, Y, INCY ) dot xHy C, Z

FUNCTION xxDOT ( N, X, INCX, Y, INCY ) dot + xTy SDS

FUNCTION xNRM2 ( N, X, INCX ) nrm2 jjxjj2 S, D, SC, DZ

FUNCTION xASUM ( N, X, INCX ) asum jjre(x)jj1+jjim(x)jj1 S, D, SC, DZ

FUNCTION IxAMAX( N, X, INCX ) amax 1stk3jre(xk)j+jim(xk)j S, D, C, Z

=max(jre(xi)j+jim(xi)j)

Level2BLAS

options dim b-width scalar matrix vector scalar vector

xGEMV ( TRANS, M, N, ALPHA, A, LDA, X, INCX, BETA, Y, INCY ) y Ax + y;y ATx + y;y AHx + y;A mn S, D, C, Z

xGBMV ( TRANS, M, N, KL, KU, ALPHA, A, LDA, X, INCX, BETA, Y, INCY ) y Ax + y;y ATx + y;y AHx + y;A mn S, D, C, Z

xHEMV ( UPLO, N, ALPHA, A, LDA, X, INCX, BETA, Y, INCY ) y Ax + y C, Z

xHBMV ( UPLO, N, K, ALPHA, A, LDA, X, INCX, BETA, Y, INCY ) y Ax + y C, Z

xHPMV ( UPLO, N, ALPHA, AP, X, INCX, BETA, Y, INCY ) y Ax + y C, Z

xSYMV ( UPLO, N, ALPHA, A, LDA, X, INCX, BETA, Y, INCY ) y Ax + y S, D

xSBMV ( UPLO, N, K, ALPHA, A, LDA, X, INCX, BETA, Y, INCY ) y Ax + y S, D

xSPMV ( UPLO, N, ALPHA, AP, X, INCX, BETA, Y, INCY ) y Ax + y S, D

xTRMV ( UPLO, TRANS, DIAG, N, A, LDA, X, INCX ) x Ax;x ATx;x AHx S, D, C, Z

xTBMV ( UPLO, TRANS, DIAG, N, K, A, LDA, X, INCX ) x Ax;x ATx;x AHx S, D, C, Z

xTPMV ( UPLO, TRANS, DIAG, N, AP, X, INCX ) x Ax;x ATx;x AHx S, D, C, Z

xTRSV ( UPLO, TRANS, DIAG, N, A, LDA, X, INCX ) x A1x;x ATx;x AHx S, D, C, Z

xTBSV ( UPLO, TRANS, DIAG, N, K, A, LDA, X, INCX ) x A1x;x ATx;x AHx S, D, C, Z

xTPSV ( UPLO, TRANS, DIAG, N, AP, X, INCX ) x A1x;x ATx;x AHx S, D, C, Z

options dim scalar vector vector matrix

xGER ( M, N, ALPHA, X, INCX, Y, INCY, A, LDA ) A xyT+A;A mn S, D

xGERU ( M, N, ALPHA, X, INCX, Y, INCY, A, LDA ) A xyT+A;A mn C, Z

xGERC ( M, N, ALPHA, X, INCX, Y, INCY, A, LDA ) A xyH+A;A mn C, Z

xHER ( UPLO, N, ALPHA, X, INCX, A, LDA ) A xxH+A C, Z

xHPR ( UPLO, N, ALPHA, X, INCX, AP ) A xxH+A C, Z

xHER2 ( UPLO, N, ALPHA, X, INCX, Y, INCY, A, LDA ) A xyH+y(x)H+A C, Z

xHPR2 ( UPLO, N, ALPHA, X, INCX, Y, INCY, AP ) A xyH+y(x)H+A C, Z

xSYR ( UPLO, N, ALPHA, X, INCX, A, LDA ) A xxT+A S, D

xSPR ( UPLO, N, ALPHA, X, INCX, AP ) A xxT+A S, D

xSYR2 ( UPLO, N, ALPHA, X, INCX, Y, INCY, A, LDA ) A xyT+yxT+A S, D

xSPR2 ( UPLO, N, ALPHA, X, INCX, Y, INCY, AP ) A xyT+yxT+A S, D

Level3BLAS

options dim scalar matrix matrix scalar matrix

xGEMM ( 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 mn S, D, C, Z

xSYMM ( SIDE, UPLO, M, N, ALPHA, A, LDA, B, LDB, BETA, C, LDC ) C AB + C;C BA + C;C mn;A = AT S, D, C, Z

xHEMM ( SIDE, UPLO, M, N, ALPHA, A, LDA, B, LDB, BETA, C, LDC ) C AB + C;C BA + C;C mn;A = AH C, Z

xSYRK ( UPLO, TRANS, N, K, ALPHA, A, LDA, BETA, C, LDC ) C AAT+C;C ATA + C;C nn S, D, C, Z

xHERK ( UPLO, TRANS, N, K, ALPHA, A, LDA, BETA, C, LDC ) C AAH+C;C AHA + C;C nn C, Z

xSYR2K( UPLO, TRANS, N, K, ALPHA, A, LDA, B, LDB, BETA, C, LDC ) C ABT+ BAT+C;C ATB + BTA + C;C nn S, D, C, Z

xHER2K( UPLO, TRANS, N, K, ALPHA, A, LDA, B, LDB, BETA, C, LDC ) C ABH+ BAH+C;C AHB + BHA + C;C nn C, Z

xTRMM ( SIDE, UPLO, TRANSA, DIAG, M, N, ALPHA, A, LDA, B, LDB ) B op(A)B;B Bop(A);op(A) = A;AT;AH;B mn S, D, C, Z

xTRSM ( SIDE, UPLO, TRANSA, DIAG, M, N, ALPHA, A, LDA, B, LDB ) B op(A1)B;B Bop(A1);op(A) = A;AT;AH;B mn S, D, C, Z

2

(11)

CBLAS

for(int iter=0;iter<n;iter++) {

atimesx(A,x,grad); // externe pour grad=Ax cblas_daxpy( n,-1,f,1,grad,1); // grad[i] -= f[i];

double norm2min; // normg2 = scal(grad,grad) double normg2 = cblas_ddot(n,grad,1,grad,1);

if(!iter) norm2min = normg2*1.0e-8;

if(normg2<norm2min) break;

double gamma = normg2/normg2old;

cblas_dscal(n,gamma,h,1); //h[i] = gamma*h[i]-grad[i]

cblas_daxpy( n, -1., grad,1, h, 1); h[0]=0;

double rho = cblas_ddot(n,h,1,grad,1); //rho=scal(h,grad) atimesx(A,h,grad);

rho /= cblas_ddot(n,h,1,grad,1); //rho /= scal(h,grad) cblas_daxpy( n, -rho, h,1, x, 1); // x[i] -= rho*h[i];

}

cblas est adapté du Fortran: blas1, blas2, blas3

Intégré aatlasetblitz(mais attention pour la suite) suredpblas.cpple cpu est divisé par 3!

(12)

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;

}

(13)

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++) {

atimesx(A,x,g); for(int i=0;i<n;i++) g[i] -= f[i];

double norm2min, normg2 = ddot(g,g);

if(!iter) norm2min = normg2*1.0e-8;

if(normg2<norm2min) break;

double gamma = normg2/normg2old;

for(int i=0;i<n;i++) h[i] = gamma * h[i] - g[i];

double rho = ddot(h,g);

atimesx(A,h,g); rho /= ddot(h,g);

for(int i=0;i<n;i++) x[i] -= rho*h[i];

} }

(14)

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 versionGalileode Eclipse C++, de-zipper et tester (voir plus bas).

Vous avez maintenant les outils pour le C++, l’openMP, le MPI.

(15)

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

(16)

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 debuggeurgdb

Permet de gérer des makefiles complexes (calcul // entre autre) Diminue le temps de développement

(17)

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) avecu(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...

(18)

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

(19)

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 FinisP1 Parallélisation en OpenMP

(20)

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

(21)

Outline III

Méthodes de Schwarz Méthode de Schur

Méthodes Lagrangienne et Mortier-Joint

(22)

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!

(23)

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

(24)

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

(25)

Les outils Middleware (intergiciels!)

openMP

MPI (openMPI et MPICH2) Globus et mpich-G

upc-Berkeley, chapel CUDA, openCL

(26)

Exemple 1. Calcul d’une option en finance

Le sousjacentSt est modélisé par une EDO-S dSt =St(rdt+σdWt), S(0) =S0

Le put est calculé parP0=e−rTE(K−ST)+ La loi des grands nombres⇒ P0e−rTM (K −STi )+ On utilise des différences finies et on simuledWt =√

dtN(0,1), Sm+1=Sm+δtSm(rδt+σ√

δtN(0,1)) N(0,1) =p

−2 logxcos(2πy)x,y aleatoires uniformes∈(0,1).

Le calcul desSTi est “embarrassingly parallel".

Voici le code C

(27)

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;

}

(28)

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;

}

time0-=CPUtime();

printf("P_0 = %f CPUtime=%f \n",P0*exp(-r*T)/kmax, -time0);

return 0;

}

Exercice: En vue du parallélisme proposer une scission de la partie qui prend du temps en 2 blocs indépendants.

(29)

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 FinisP1 Parallélisation en OpenMP

(30)

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

(31)

Outline III

Méthodes de Schwarz Méthode de Schur

Méthodes Lagrangienne et Mortier-Joint

(32)

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

(33)

Hello world

#include <omp.h>

#include <stdio.h>

#include <stdlib.h>

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 avecg++ -fopenmp hellomp.c -o hello(peut demanderexport PATH=/usr/local/bin:$PATH) resultat de ./hello: 0 5 1 6 2 7 3 8 4 9 CPUtime=0.000633Si dans eclipse il faut changer projet/properties/settings/linker

(34)

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

(35)

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 sascalabilité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.

(36)

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

(37)

edostochOMP.c I

(38)

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.

(39)

Produit Matrice Vecteur (Juvigny) I

(40)

Produit Matrice Vecteur (Juvigny) II

(41)

Produit Matrice Vecteur (Juvigny) III

(42)

Exercices pour le TD

1 Lanceredostochomp.cet étudier les perfs en fonctions de P

2 ChangerS[]en une seule variable et utiliserreduce; il faudra aussi utiliser la fonctionrand_r(state)qui, elle, est réentrante.

3 Lancerprog2.cpour comparer openMP et BLAS

4 Modifier le code pour utiliser openMP ET cblas.

5 Mettre des directives openMP dans le prgrammevanilafem.c çi-dessous.

(43)

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

Z L 0

um+1−um

δt w(x)dx + Z L

0

κ∂xum+1xw = Z L

0

fw ∀w ∈V :=H01(0,L) Discretisation en espace par éléments finis de degrés 1: on remplace V parVh, l’espace des fonctions continues affines par morceaux sur [0,L] =∪i[xi,xi+1]avecxi =ih,i=0..I-1, tel queIh=L. On obtient un système lineaire a chaque itération pourUm+1∈ RN:

B(Um+1−Um) +AUm+1=F ∈ RN, avecBij = 1

δt Z L

0

wiwjdx, Aij = Z L

0

κ∇wi∇wjdx oùwi est la fonction deVhqui vautδij enxj.

(44)

Equation de la chaleur: discretisation

Il est facile de voir queAetB sont tridiagonales avec Bii = 2h

δt, Bi,i−1=Bi,i+1= h

δt, Aii = 2κ

h , Ai,i−1=Ai,i+1=−κ h A priori le système tridiagonal pourUm+1is 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 thenu=0 atxm;u=0 atxM anyway but ifxMis 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.

(45)

Le code vanilafem.c (I)

(46)

Le code vanilafem.c (II)

(47)

Le code vanilafem.c (III)

(48)

Le code vanilafem.c (IV)

(49)

Le code vanilafem.c (V)

(50)

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 FinisP1 Parallélisation en OpenMP

(51)

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

(52)

Outline III

Méthodes de Schwarz Méthode de Schur

Méthodes Lagrangienne et Mortier-Joint

(53)

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.

ApresMPI_init()et jusqu’aMPI_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.

(54)

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

(55)

Produit matrice vecteur

On exploite le fait queAest tridiagonal:

si{xi}iiM−1

m est dans un banc mémoirep

Axi =aixi−1+bixi+cixi+1demande la reception de xim−1et dexiM des bancs mémoiresp−1 etp+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];

}

(56)

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.

double Option::scal (const Vector& v1,const Vector& v2){

double S,s=0;

for(int i=im1; i<iM1;i++) s += v1[i] * v2[i];

MPI_Barrier(MPI_COMM_WORLD);

MPI_Reduce(&s, &S, 1, MPI_DOUBLE, MPI_SUM,0,MPI_COMM_WORLD);

MPI_Bcast(&S, 1, MPI_DOUBLE,0, MPI_COMM_WORLD);

return S;

}

Noter que la mémoire n’est pas optimisée et qu’il faudrait decaller les indices et accéder àv[i−im1].

(57)

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);

(58)

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.

(59)

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 FinisP1 Parallélisation en OpenMP

(60)

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

(61)

Outline III

Méthodes de Schwarz Méthode de Schur

Méthodes Lagrangienne et Mortier-Joint

(62)

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 deshared 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 Churchde CRAY research etCAF/Fortran ainsi queTitanium/Java.

(63)

Organisation mémoire

Le programme est recopié dans chaque proc, chaque variable est en

THREADS exemplaires sauf si elle est déclaréeshared; dans ce ca elle est par defaut sur la mémoire du process 0. Lesshared arraysont distribués:

#define N 1000 int i;

shared double x, y[N]

shared [2] double a[N];

Chaque proc accède a toute variablesharedet connait sonaffinity. Si THREADS=10, il y aura 10 instances dei,une seule dexet dans Thread0, une seule de chaquey[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...

(64)

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.

(65)

Exemple: addition de 2 vecteurs (II)

On peut utiliser une fonction de la bibliothèquebupc

#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!

(66)

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)

localSum += a[j] + b[j] ;

double sum = bupc_allv_reduce(double, localSum, 0, UPC_ADD);

if(MYTHREAD==0) printf("sum = %f \n", sum );

return 0;

}

Leupc_forallest un “parallel for” où le dernier argument indique qui fera l’opération. Ici l’affinité deidétermine le proc: commei est local, c’est lorsque lei 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] ;

(67)

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;

}

sum = -4294967296000000.000000 CPUtime=0.410912 sur 1 proc sum = -4294967296000000.000000 CPUtime=0.234346 sur 2 proc

(68)

Exemple: edostch.upc

(69)

Locks

Notez la séquence shared double PT;

upc_lock_t* L= upc_lock_alloc();

...

upc_forall(...) {

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é enstrict shared doublealors 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

(70)

Exemple:vanilafem.upc (I)

(71)

Exemple: vanilafem.upc (II)

(72)

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

(73)

Exemple 2(I): vanilafem2.upc

(74)

Exemple 2(II): vanilafem2.upc

(75)

Exemple 2(III): vanilafem2.upc

(76)

Exemple 2(IV): vanilafem2.upc

(77)

Exemple 2(V): vanilafem2.upc

(78)

Exemple 2(V): vanilafem2.upc

(79)

Exercices pour le TD

1 Lanceredostoch.upcet étudier les perfs en fonctions du nombre de proc

2 Vérifier que le programmevanilafem0.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

programmevanilafem0.upcpour obtenir de bonnes perfs et des résultats justes en multi-proc.

4 Etudier les perf en fonction du nombre de proc

(80)

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 FinisP1 Parallélisation en OpenMP

(81)

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

(82)

Outline III

Méthodes de Schwarz Méthode de Schur

Méthodes Lagrangienne et Mortier-Joint

(83)

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 commebrook, puis CUDA; le langage OpenCL est un travail d’équipe (consortium Khronos).

•Intel nous prommet avecLarrabeeun processeurs sur le principe des GPGPU: 32 CPU avec des mémoires hiérarchiques et des communications rapides.

(84)

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

(85)

Le Modèle de mémoires de Nvidia (I)

(86)

Le Modèle de mémoires de Nvidia (II)

(87)

Le Modèle de mémoires de Nvidia (III)

(88)

Programmation en CUDA

Nous allons ecrire un priceur d’option put basé sur la formule

STn =S0e(r−12σ2)T

T Nn(0,1), PT = e−rT N

N

X

n=1

(K −STn)+

Cette formule vient d’une solution analytique de l’EDS de

Black-Scholes pourSt lorsquer etσ sont constants. Nous allons utiliser la formule de Cox-Muller pour générer les réalisationsNnde la variable aléatoire gaussienneN :

N(0,1) =p

−2 log(x)cos(2πy), x,y aleatoires uniformes sur (0,1)

•xn,ynsont générées parrandom()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,yndeB1,B2 et

•le resultat est stocké dans B2 et renvoyé par recopié dans A2.

(89)

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 faireexport PATH=/usr/local/cuda/bin:$PATH

export DYLD_LIBRARY_PATH

=/usr/local/cuda/lib:$DYLD_LIBRARY_PATH Pour compiler il faut

nvcc -deviceemu BSCuda.cu Pour lancer l’exécutable il faut./a.out

(90)

Implémentation des formules (cf. BSCuda.cu)

BSgpu et BScpu appelle BS sur chaque éléments des tableaux.

(91)

Transfer du CPU au GPU

(92)

Calcul dans le GPU

Exécute BSgpu sur Nthreads=512 chacun prenant en charge Nblocks=256 et copie les résultats dans A2

(93)

Portage de vanilafem.c sous CUDA avec cublas

Preambule

(94)

Multiplication Matrice Vector (cf. testcublas.cu)

Utilisation de cblas

(95)

Préparation de l’appel d’une fonction cublas

(96)

Appel de la fonction de cublas

(97)

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.

(98)

La méthode de Jacobi

En différences finies le probleme−u” =1, u(0) =u(1) =0 devient Au=1 ouAest une matrice tridiagonale d’éléments(−1,2,−1)h−2, oùhest la taille du maillage. Jacobi, c’est itérer sur l’équation:

vi = (ui+1+ui−1+h2)/2, ∀ipuisui =vi ∀i

Gauss-Seidel rouge noir, cela consiste a faire

ui = (ui+1+ui−1+h2)/2, ∀ipairs puis pour tout i impair ui = (ui+1+ui−1+h2)/2

(99)

Programmation en CUDA de la méthode de Jacobi (I)

(100)

Programmation en CUDA de la méthode de Jacobi (II)

(101)

openCL sur Mac OSX 10.6

(102)

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;});

(103)

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.

(104)

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 FinisP1 Parallélisation en OpenMP

(105)

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

(106)

Outline III

Méthodes de Schwarz Méthode de Schur

Méthodes Lagrangienne et Mortier-Joint

(107)

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 fonctionpartmesh, 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.2etsimpletest.txt.npart.2

Références

Documents relatifs

on the decision to delegate the task management to OpenMP, the task granularity is en- forced to reach high performance, while the task submission order is a consequence of the need

Cette clause permet au programmeur de donner des informations au support exécutif à propos du placement de la tâche au cours de l’exécution, ce qui peut également être utilisé par

Là où cela se complique, c’est effectivement lorsqu’au moins un parmi plusieurs processus légers d’un même processus lourd doit communiquer dans l’univers MPI. Dans ce

The functions get_grid_size(), cell_grid.size(), cs_vec.size() were called many times, for instance in the function broadphase(), in the initial version and they represented

In the first example on the left, the task reads from the stream x, reading up to horizon values of x ahead of the current position in the stream and consumes burst elements at

We promote firstprivate clauses to input clauses in streaming tasks as our choice of a persistent- task execution model means the expansion of the clause needs a stream to

Dans le cadre d’un modèle gravitaire, si les moyennes harmonique et géométrique montrent leurs performances à réduire le nombre de véhicules, cela se fait au détriment des temps

Este trabalho implementa a an´alise de um conjunto de dados sobre a espessura da camada de ozˆonio terrestre, usando as ferramentas de programac¸˜ao paralela OpenMP e MPI,