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



Documents pareils
Introduction au pricing d option en finance

Initiation au HPC - Généralités

I00 Éléments d architecture

Introduction au langage C

Le langage C. Séance n 4

Introduction à la Programmation Parallèle: MPI

Architecture des ordinateurs

Programmation C. Apprendre à développer des programmes simples dans le langage C

1/24. I passer d un problème exprimé en français à la réalisation d un. I expressions arithmétiques. I structures de contrôle (tests, boucles)

Éléments d informatique Cours 3 La programmation structurée en langage C L instruction de contrôle if

Génération de code binaire pour application multimedia : une approche au vol

Algorithmique et Programmation, IMA

Limitations of the Playstation 3 for High Performance Cluster Computing

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

Systèmes parallèles et distribués


Table des matières PRESENTATION DU LANGAGE DS2 ET DE SES APPLICATIONS. Introduction

Introduction à CUDA.

Introduction à MATLAB R

IN Cours 1. 1 Informatique, calculateurs. 2 Un premier programme en C

M2-Images. Rendu Temps Réel - OpenGL 4 et compute shaders. J.C. Iehl. December 18, 2013

Résolution de systèmes linéaires par des méthodes directes

1. Structure d un programme C. 2. Commentaire: /*..texte */ On utilise aussi le commentaire du C++ qui est valable pour C: 3.

INFO-F-404 : Techniques avancées de systèmes d exploitation

DE L ALGORITHME AU PROGRAMME INTRO AU LANGAGE C 51

Segmentation d'images à l'aide d'agents sociaux : applications GPU

Quelques éléments de compilation en C et makefiles

Cours d Algorithmique-Programmation 2 e partie (IAP2): programmation 24 octobre 2007impérative 1 / 44 et. structures de données simples

Quantification d incertitude et Tendances en HPC

Bases de programmation. Cours 5. Structurer les données

Eléments d architecture des machines parallèles et distribuées

EPREUVE OPTIONNELLE d INFORMATIQUE CORRIGE

Cours d initiation à la programmation en C++ Johann Cuenin

Cours 1 : Qu est-ce que la programmation?

Info0101 Intro. à l'algorithmique et à la programmation. Cours 3. Le langage Java

Cours intensif Java. 1er cours: de C à Java. Enrica DUCHI LIAFA, Paris 7. Septembre Enrica.Duchi@liafa.jussieu.fr

03/04/2007. Tâche 1 Tâche 2 Tâche 3. Système Unix. Time sharing

TP1 : Initiation à Java et Eclipse

Architecture des calculateurs

Contrôle Non Destructif : Implantation d'algorithmes sur GPU et multi-coeurs. Gilles Rougeron CEA/LIST Département Imagerie Simulation et Contrôle

Le Langage C Version 1.2 c 2002 Florence HENRY Observatoire de Paris Université de Versailles florence.henry@obspm.fr

Introduction au calcul parallèle avec OpenCL

Une bibliothèque de templates pour CUDA

Optimisation de logiciels de modélisation sur centre de calcul

Initiation à la programmation en Python

L informatique en BCPST

ACTIVITÉ DE PROGRAMMATION

Initiation. àl algorithmique et à la programmation. en C

Licence Sciences et Technologies Examen janvier 2010

Algorithmique & Langage C IUT GEII S1. Notes de cours (première partie) cours_algo_lgc1.17.odp. Licence

Java Licence Professionnelle CISII,

Informatique Générale

Architecture des ordinateurs

Programmation système I Les entrées/sorties

1) Installation de Dev-C++ Téléchargez le fichier devcpp4990setup.exe dans un répertoire de votre PC, puis double-cliquez dessus :

Tests de performance du matériel

TP 1. Prise en main du langage Python

Cours 1 : La compilation

Performances et optimisations

Métriques de performance pour les algorithmes et programmes parallèles

as Architecture des Systèmes d Information

Guide d installation JMap 5.0

Cours 7 : Utilisation de modules sous python

Cours d analyse numérique SMI-S4

Evaluation des performances de programmes parallèles haut niveau à base de squelettes

Rapport 2014 et demande pour Portage de Méso-NH sur Machines Massivement Parallèles du GENCI Projet 2015 : GENCI GEN1605 & CALMIP-P0121

UE Programmation Impérative Licence 2ème Année

Gestion de clusters de calcul avec Rocks


Environnements de développement (intégrés)

Hiérarchie matériel dans le monde informatique. Architecture d ordinateur : introduction. Hiérarchie matériel dans le monde informatique

Le prototype de la fonction main()

. Plan du cours. . Architecture: Fermi ( ), Kepler (12-?)

Plan du cours. Historique du langage Nouveautés de Java 7

Conventions d écriture et outils de mise au point

1-Introduction 2. 2-Installation de JBPM 3. 2-JBPM en action.7

Sur un ordinateur portable ou un All-in-One tactile, la plupart des éléments mentionnés précédemment sont regroupés. 10) 11)

Rapport de stage Master 2

IFT Systèmes d exploitation - TP n 1-20%

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

Cours de C. Petits secrets du C & programmation avancée. Sébastien Paumier

MICROINFORMATIQUE NOTE D APPLICATION 1 (REV. 2011) ARITHMETIQUE EN ASSEMBLEUR ET EN C

TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile

4. Outils pour la synchronisation F. Boyer, Laboratoire Lig

Info0804. Cours 6. Optimisation combinatoire : Applications et compléments

TP, première séquence d exercices.

Éléments d'architecture des ordinateurs

Compilation (INF 564)

Généralités sur le Langage Java et éléments syntaxiques.

Cryptographie RSA. Introduction Opérations Attaques. Cryptographie RSA NGUYEN Tuong Lan - LIU Yi 1

4 Exemples de problèmes MapReduce incrémentaux

Corrigé des TD 1 à 5

Programmer en JAVA. par Tama

Introduction à Java. Matthieu Herrb CNRS-LAAS. Mars

Programmation en Java IUT GEII (MC-II1) 1

Introduction à la programmation orientée objet, illustrée par le langage C++ Patrick Cégielski

Cours Programmation Système

Eclipse atelier Java

Infrastructures Parallèles de Calcul

Transcription:

Optimisation des performances et Parallélisme en C/C++ - openmp - MPI - UPC - CUDA -opencl http://www.ann.jussieu.fr/pironneau Olivier Pironneau 1 1 University of Paris VI, Laboratoire J.-L. Lions, Olivier.Pironneau@upmc.fr Cours Mastère 2, Automne 2009 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC - CUDA 1 / 118-op

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 P 1 Parallélisation en OpenMP Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC - CUDA 2 / 118-op

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 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC - CUDA 3 / 118-op

Outline III Méthodes de Schwarz Méthode de Schur Méthodes Lagrangienne et Mortier-Joint Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC - CUDA 4 / 118-op

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". Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC - CUDA 5 / 118-op

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. Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC - CUDA 6 / 118-op

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. Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC - CUDA 7 / 118-op

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]; Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC - CUDA 8 / 118-op

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 + +){ g n = Ax n f γ = gn 2 g n 1 2 h n = γh n 1 g n ρ = hn g n h n Ah n x n = x n 1 + ρh n } Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC - CUDA 9 / 118-op

CBLAS memento 5-elementarray prexes SUBROUTINExROTG( A,B,C,S) Generateplanerotation SUBROUTINExROTMG( D1,D2,A,B, Generatemodiedplanerotation SUBROUTINExROT(N, Applyplanerotation SUBROUTINExROTM(N, X,INCX,Y,INCY, PARAM) Applymodiedplanerotation Level1BLASdimscalarvectorvectorscalars x$y SUBROUTINExSCAL(N,ALPHA,X,INCX) x S,D,C,Z,CS,ZD SUBROUTINExCOPY(N, x SUBROUTINExAXPY(N,ALPHA,X,INCX,Y,INCY) y x+y FUNCTIONxDOT(N, S,D,DS FUNCTIONxDOTU(N, SUBROUTINExSWAP(N, xhy C,Z FUNCTIONxxDOT(N, X,INCX,Y,INCY) dot +xty SDS FUNCTIONxNRM2(N, nrm2 jjxjj2 FUNCTIONxASUM(N, X,INCX) asum jjre(x)jj1+jjim(x)jj1 S,D,SC,DZ FUNCTIONxDOTC(N, X,INCX) amax 1stk3jre(xk)j+jim(xk)j S,D,C,Z =max(jre(xi)j+jim(xi)j) Level2BLAS options dimb-widthscalarmatrixvectorscalarvector xgemv( FUNCTIONIxAMAX(N, TRANS, M,N,KL,KU,ALPHA,A,LDA,X,INCX,BETA,Y,INCY) Ax+y;y ATx+y;y AHx+y;A mn S,D,C,Z xhemv(uplo, xhbmv(uplo, xhpmv(uplo, xsymv(uplo, xsbmv(uplo, ALPHA,A,LDA,X,INCX,BETA,Y,INCY) xgbmv( ALPHA,AP, y Ax+y xtrmv(uplo,trans,diag, xtbmv(uplo,trans,diag, N,K, A,LDA,X,INCX) xtpmv(uplo,trans,diag, AP, x Ax;x ATx;x AHx S,D,C,Z xspmv(uplo, xtbsv(uplo,trans,diag, N,K, A,LDA,X,INCX) xtpsv(uplo,trans,diag, AP, x A 1x;x A Tx;x A Hx S,D,C,Z options dimscalarvectorvectormatrix xger( xtrsv(uplo,trans,diag, xyt+a;a mn xgerc( M,N,ALPHA,X,INCX,Y,INCY,A,LDA) xyh+a;a mn xher(uplo, A,LDA) xhpr(uplo, AP) xxh+a xher2(uplo, xgeru( N,ALPHA,X,INCX,Y,INCY,AP) xyh+y(x)h+a C,Z xsyr(uplo, A,LDA) xspr(uplo, AP) xxt+a xsyr2(uplo, N,ALPHA,X,INCX,Y,INCY,A,LDA) A xyt+yxt+a S,D xhpr2(uplo, N,ALPHA,X,INCX,Y,INCY,AP) A xyt+yxt+a S,D Level3BLAS options dim scalarmatrixmatrixscalarmatrix xspr2(uplo, TRANSA,TRANSB, op(a)op(b)+c;op(x)=x;xt;xh;c mn xsymm(side,uplo, BA+C;C mn;a=at xhemm(side,uplo, BA+C;C mn;a=ah xsyrk( AAT+C;C BETA,C,LDC)C AHA+C;C nn xgemm( M,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC)C Optimisation des performances AB+C;C et Parallélisme en C/C++ - ATA+C;C nn openmp - MPI MPE - UPC -10 CUDA / 118-op B op(a 1)B;B Bop(A 1);op(A)=A;AT;AH;B mns,d,c,z 2 Bop(A);op(A)=A;AT;AH;B mn op(a)b;b AHB+BHA+C;C nnc,z ABH+BAH+C;C ATB+BTA+C;C nn ABT+BAT+C;C C,Z AAH+C;C xherk( ALPHA,A,LDA,B,LDB) DIAG,M,N, xtrsm(side,uplo,transa, xtrmm(side,uplo,transa, N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC)C UPLO,TRANS, xher2k( xsyr2k(

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é a atlas et blitz (mais attention pour la suite) sur edpblas.cpp le cpu est divisé par 3! Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -11 CUDA / 118-op

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; } Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -12 CUDA / 118-op

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]; } } Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -13 CUDA / 118-op

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. Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -14 CUDA / 118-op

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 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -15 CUDA / 118-op

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 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -16 CUDA / 118-op

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... Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -17 CUDA / 118-op

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 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -18 CUDA / 118-op

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 P 1 Parallélisation en OpenMP Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -19 CUDA / 118-op

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 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -20 CUDA / 118-op

Outline III Méthodes de Schwarz Méthode de Schur Méthodes Lagrangienne et Mortier-Joint Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -21 CUDA / 118-op

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! Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -22 CUDA / 118-op

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 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -23 CUDA / 118-op

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 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -24 CUDA / 118-op

Les outils Middleware (intergiciels!) openmp MPI (openmpi et MPICH2) Globus et mpich-g upc-berkeley, chapel CUDA, opencl Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -25 CUDA / 118-op

Exemple 1. Calcul d une option en finance Le sousjacent S t est modélisé par une EDO-S ds t = S t (rdt + σdw t ), S(0) = S 0 Le put est calculé par P 0 = e rt E(K S T ) + La loi des grands nombres P 0 e rt M (K Si T )+ On utilise des différences finies et on simule dw t = dtn (0, 1), S m+1 = S m + δts m (rδt + σ δtn (0, 1)) N (0, 1) = 2 log x cos(2πy) x,y aleatoires uniformes (0, 1). Le calcul des ST i est embarrassingly parallel". Voici le code C Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -26 CUDA / 118-op

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; } Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -27 CUDA / 118-op

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. Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -28 CUDA / 118-op

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 P 1 Parallélisation en OpenMP Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -29 CUDA / 118-op

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 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -30 CUDA / 118-op

Outline III Méthodes de Schwarz Méthode de Schur Méthodes Lagrangienne et Mortier-Joint Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -31 CUDA / 118-op

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 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -32 CUDA / 118-op

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 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 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -33 CUDA / 118-op

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 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -34 CUDA / 118-op

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. Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -35 CUDA / 118-op

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 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -36 CUDA / 118-op

edostochomp.c I Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -37 CUDA / 118-op

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. Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -38 CUDA / 118-op

Produit Matrice Vecteur (Juvigny) I Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -39 CUDA / 118-op

Produit Matrice Vecteur (Juvigny) II Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -40 CUDA / 118-op

Produit Matrice Vecteur (Juvigny) III Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -41 CUDA / 118-op

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. Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -42 CUDA / 118-op

Equation de la chaleur t u x (κ x u) = f, u(0, t) = u(l, t) = 0, u(x, 0) = u 0 (x) x, t (0, L) Formulation variationnelle et differences finies en temps L 0 u m+1 u m w(x)dx + δt L 0 κ x u m+1 x w = L 0 fw w V := H0 1 (0, L) Discretisation en espace par éléments finis de degrés 1: on remplace V par V h, l espace des fonctions continues affines par morceaux sur [0, L] = i [x i, x i+1 ] avec x i = ih,i=0..i-1, tel que Ih = L. On obtient un système lineaire a chaque itération pour U m+1 R N : B(U m+1 U m ) + AU m+1 = F R N, avec B ij = 1 δt L 0 w i w j dx, A ij = où w i est la fonction de V h qui vaut δ ij en x j. L 0 κ w i w j dx Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -43 CUDA / 118-op

Equation de la chaleur: discretisation Il est facile de voir que A et B sont tridiagonales avec B ii = 2h δt, B i,i 1 = B i,i+1 = h δt, A ii = 2κ h, A i,i 1 = A i,i+1 = κ h A priori le système tridiagonal pouru m+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: t u + ru rx x u σ2 x 2 2 xxu = 0, u(t = 0) = max(k x, 0) If there is a low-barrier then u = 0 at x m; u = 0 at x M anyway but if x M 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. Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -44 CUDA / 118-op

Le code vanilafem.c (I) Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -45 CUDA / 118-op

Le code vanilafem.c (II) Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -46 CUDA / 118-op

Le code vanilafem.c (III) Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -47 CUDA / 118-op

Le code vanilafem.c (IV) Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -48 CUDA / 118-op

Le code vanilafem.c (V) Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -49 CUDA / 118-op

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 P 1 Parallélisation en OpenMP Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -50 CUDA / 118-op

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 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -51 CUDA / 118-op

Outline III Méthodes de Schwarz Méthode de Schur Méthodes Lagrangienne et Mortier-Joint Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -52 CUDA / 118-op

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. Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -53 CUDA / 118-op

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 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -54 CUDA / 118-op

Produit matrice vecteur On exploite le fait que A est tridiagonal: si {x i } i M 1 i m est dans un banc mémoire p Ax i = a i x i 1 + b i x i + c i x i+1 demande la reception de x im 1 et de x im des bancs mémoires p 1 et p + 1. void Option::atimesx(Vector& a, Vector& b, Vector& c, Vector& x,ve 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]; } Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -55 CUDA / 118-op

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]. Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -56 CUDA / 118-op

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); Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -57 CUDA / 118-op

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. Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -58 CUDA / 118-op

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 P 1 Parallélisation en OpenMP Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -59 CUDA / 118-op

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 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -60 CUDA / 118-op

Outline III Méthodes de Schwarz Méthode de Schur Méthodes Lagrangienne et Mortier-Joint Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -61 CUDA / 118-op

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. Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -62 CUDA / 118-op

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... Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -63 CUDA / 118-op

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. Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -64 CUDA / 118-op

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! Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -65 CUDA / 118-op

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; } 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] ; Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -66 CUDA / 118-op

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 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -67 CUDA / 118-op

Exemple: edostch.upc Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -68 CUDA / 118-op

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é 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 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -69 CUDA / 118-op

Exemple:vanilafem.upc (I) Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -70 CUDA / 118-op

Exemple: vanilafem.upc (II) Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -71 CUDA / 118-op

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 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -72 CUDA / 118-op

Exemple 2(I): vanilafem2.upc Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -73 CUDA / 118-op

Exemple 2(II): vanilafem2.upc Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -74 CUDA / 118-op

Exemple 2(III): vanilafem2.upc Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -75 CUDA / 118-op

Exemple 2(IV): vanilafem2.upc Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -76 CUDA / 118-op

Exemple 2(V): vanilafem2.upc Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -77 CUDA / 118-op

Exemple 2(V): vanilafem2.upc Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -78 CUDA / 118-op

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 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -79 CUDA / 118-op

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 P 1 Parallélisation en OpenMP Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -80 CUDA / 118-op

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 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -81 CUDA / 118-op

Outline III Méthodes de Schwarz Méthode de Schur Méthodes Lagrangienne et Mortier-Joint Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -82 CUDA / 118-op

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. Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -83 CUDA / 118-op

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 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -84 CUDA / 118-op

Le Modèle de mémoires de Nvidia (I) Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -85 CUDA / 118-op

Le Modèle de mémoires de Nvidia (II) Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -86 CUDA / 118-op

Le Modèle de mémoires de Nvidia (III) Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -87 CUDA / 118-op

Programmation en CUDA Nous allons ecrire un priceur d option put basé sur la formule S n T = S 0e (r 1 2 σ2 )T +σ T N n (0,1), P T = e rt N N (K ST n )+ Cette formule vient d une solution analytique de l EDS de Black-Scholes pour S t lorsque r et σ sont constants. Nous allons utiliser la formule de Cox-Muller pour générer les réalisations N n de la variable aléatoire gaussienne N : N(0, 1) = 2 log(x) cos(2πy), x, y aleatoires uniformes sur (0,1) x n, y n 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 x n, y n de B1, B2 et le resultat est stocké dans B2 et renvoyé par recopié dans A2. n=1 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -88 CUDA / 118-op

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 Pour compiler il faut nvcc -deviceemu BSCuda.cu Pour lancer l exécutable il faut./a.out Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -89 CUDA / 118-op

Implémentation des formules (cf. BSCuda.cu) BSgpu et BScpu appelle BS sur chaque éléments des tableaux. Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -90 CUDA / 118-op

Transfer du CPU au GPU Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -91 CUDA / 118-op

Calcul dans le GPU Exécute BSgpu sur Nthreads=512 chacun prenant en charge Nblocks=256 et copie les résultats dans A2 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -92 CUDA / 118-op

Portage de vanilafem.c sous CUDA avec cublas Preambule Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -93 CUDA / 118-op

Multiplication Matrice Vector (cf. testcublas.cu) Utilisation de cblas Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -94 CUDA / 118-op

Préparation de l appel d une fonction cublas Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -95 CUDA / 118-op

Appel de la fonction de cublas Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -96 CUDA / 118-op

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. Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -97 CUDA / 118-op

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: v i = (u i + 1 + u i 1 + h 2 )/2, i puis u i = v i i Gauss-Seidel rouge noir, cela consiste a faire u i = (u i+1 + u i 1 + h 2 )/2, i pairs puis pour tout i impair u i = (u i+1 + u i 1 + h 2 )/2 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -98 CUDA / 118-op

Programmation en CUDA de la méthode de Jacobi (I) Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE - UPC -99 CUDA / 118-op

Programmation en CUDA de la méthode de Jacobi (II) Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE- UPC100 - CUDA / 118-op

opencl sur Mac OSX 10.6 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE- UPC101 - CUDA / 118-op

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;}); Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE- UPC102 - CUDA / 118-op

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. Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE- UPC103 - CUDA / 118-op

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 P 1 Parallélisation en OpenMP Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE- UPC104 - CUDA / 118-op

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 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE- UPC105 - CUDA / 118-op

Outline III Méthodes de Schwarz Méthode de Schur Méthodes Lagrangienne et Mortier-Joint Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE- UPC106 - CUDA / 118-op

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 4./partmesh simpletest.txt 2 avec simpletest = 5 6 1 6 1 2 3 7 2 4 6 2 6 3 2 4 5 6 5 6 3 7 4 2. 1 Le programme fournit en sortie deux fichiers de nom simpletest.txt.epart.2 et simpletest.txt.npart.2 3 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE- UPC107 - CUDA / 118-op

Metis: contenu des fichiers simpletest.txt 4 5 0 1 epart npart 6 0 0 7 0 0 1 1 3 1 0 2 B 1 1 C @ 0 1 A. 0 1 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. Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE- UPC108 - CUDA / 118-op

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 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE- UPC109 - CUDA / 118-op

PetSc - Présentation - Application a une méthode de sous-domaine avec gradient conjugué - Une méthode de Scharwz Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE- UPC110 - CUDA / 118-op

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 P 1 Parallélisation en OpenMP Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE- UPC111 - CUDA / 118-op

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 Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE- UPC112 - CUDA / 118-op

Outline III Méthodes de Schwarz Méthode de Schur Méthodes Lagrangienne et Mortier-Joint Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE- UPC113 - CUDA / 118-op

Méthode de Schwarz avec recouvrement On décompose Ω = Ω 1 Ω 2 avec Ω 1 Ω 2 : 1 Tant que u k 1 uk 2 Ω 1 Ω 2 > ɛ, 2 calculer u k+1 1 solution de l EDP dans Ω 1 avec u k+1 1 = u2 k sur Γ 12 3 calculer u k+1 2 solution de l EDP dans Ω 2 avec u k+1 2 = u1 k sur Γ 21 4 dans Ω 1 Ω 2 set u k+1 = 1 2 [uk+1 1 + u k+1 2 ]. Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE- UPC114 - CUDA / 118-op

Méthode de Schwarz sans recouvrement 1 Tant que u k 1 uk 2 Ω 1 Ω 2 > ɛ, 2 calculer u k+1 1 solution de l EDP dans Ω 1 avec u k+1 1 = λ k on Γ 12 ; 3 calculer u k+1 2 solution de l EDP dans Ω 2 avec u k+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 θ. Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE- UPC115 - CUDA / 118-op

Méthode de Schur Considerons le probleme d algebre linéaire avec A R n n, b R n : Trouver x R n tel que Ax = b Soit une partition de A en 4 blocks A 11 R l l, A 12 R l (n l), A 21 R (n l) l et A 22 R (n l) (n l) tel que: ( A 11 A A = 12 ) A 21 A 22. Soit b 1 le vecteur des l premiere entrées de b et b 2 le reste et de même pour x. On a: (A 11 A 12 ) ( ) ( ) x 1 b 1 A 21 A 22 x 2 = b 2 Si (A 11 ) 1 existe, alors x 1 = (A 11 ) 1 (b 1 A 12 x 2 ), et (A 22 A 21 (A 11 ) 1 A 12 )x 2 = b 2 A 21 (A 11 ) 1 b 1 La matrice A 22 A 21 (A 11 ) 1 A 12 est le complément de Schur de A. Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE- UPC116 - CUDA / 118-op

Une Méthode lagrangienne (I) Principe u = f in Ω, u Γ = 0 et une partition sans recouvrement: Ω = Ω 1 Ω 2, Σ = Ω 1 Ω 2, Ω 1 Ω 2 =. Soit u i = f in Ω i, u i Γ = 0, u i n Σ = λ, où nest une normale de Σ et où λ sera ajusté pour avoir u 1 = u 2 sur Σ. Tout ceci se est équivalent à trouver {u 1, u 2, λ} H 1 (Ω 1 ) H 1 (Ω 2 ) L 2 (Σ) tel sque Ω i u i w dx + ( 1) i Σ λw = Ω i fw dx, w H0 1 (Ω), i = 1, 2, Σ (u2 u 1 )µ = 0, µ L 2 (Σ). Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE- UPC117 - CUDA / 118-op

Implémentation Prenons des éléments finis de degré 1 pour u et 0 pour λ: Trouver u h H 0h et λ h L h tels que Ω hi uh i w hdx + ( 1) i Σ h λ h w h = Ω hi fw h dx, w H 0h, Σ h (uh 2 u1 h )µ h = 0, µ h L h, Le système linéaire généré: A 11 0 B 1 0 A 22 B 2 B 1T B 2T 0 U 1 U 2 Λ = On note w i H h et w i L 2 (Σ) les fonctions de base des 2 espaces, U i les componsantes de uj i et Λ = ((λ k )). Alors A kk ij = w i w j dx, Bij k = ( 1) k w i w j, k = 1, 2. Ω hk Σ h La méthode de Schur est bien adaptée pour construire un système linéaire en Λ par élimination de U. b 1 b 2 0. Optimisation des performances et Parallélisme en C/C++ - openmp - MPI MPE- UPC118 - CUDA / 118-op