Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ......

39
Programmation Parallèle sur CPU et GPU (GPU=Graphics Processing Unit) [email protected] www.labri.fr/perso/guenneba/pghp_IO16

Transcript of Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ......

Page 1: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

Programmation Parallèlesur CPU et GPU

(GPU=Graphics Processing Unit)

[email protected]

www.labri.fr/perso/guenneba/pghp_IO16

Page 2: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

2

Plan du cours

• Motivations pour le parallélisme et les GPUs– single core → multi-core → many-core

• CPU– Architecture– Modèle de programmation en mémoire partagé

• OpenMP

• GPU (Graphics Processing Unit)– Architecture– Modèle de programmation many-core

• CUDA

Page 3: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

3

Objectifs

• Acquérir les bases pour

– éviter les erreurs de bases dans vos propres codes

• poursuivre en auto-formation au besoin

– échanger avec des spécialistes

– savoir comparer deux solutions matérielles

• savoir adapter le matériel aux besoins

Page 4: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

4

Motivations applicatives

• Toujours plus de performance...– plus rapide : de x10 à x100 ou plus !!– résoudre des problèmes plus gros– plus de précisions– rendre possible de nouvelles applications, nouveaux algorithmes– réduire la consommation– etc.

Page 5: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

5

Motivations applicatives

• Exemples :– Simu électromag, en un point : intégration 4D

• Code initial en (mauvais) MatLab : 20min

• Code optimisé / CPU : 0.5s !!

– Simu sur GPU via MatLab : a life changer !→ utilisation de CUDA en 3A-voie B (simu)

– 3A-voie A (instrumentation) :

• Embarqué– traitement/reconstruction efficace des données...

• Free-form optics

Page 6: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

6

Code optimisé et consommation énergétique

• Exemple sur un smartphone :

conso

nombre d'opérations (+,*,etc.)

Page 7: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

7

Comment augmenter les performances ?

→ Améliorer les algorithmes(voir autres cours)

→ Augmenter la puissance de calcul ?→ Comment ?→ Comment exploiter cette puissance ?

Page 8: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

8

Loi de Moore...

• Le nombre de transistors qui peut être intégré facilement dans un microprocesseur double tout les deux ans

Page 9: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

9

Motivations pour le multi-cores

• Finesse de gravure– 32nm en 2010, 22nm en 2012, 14nm en 2014, …– demain : 10nm

→ plus de transistors par circuit

• Leviers pour augmenter les performances– avec un seul processeur :

• augmenter la fréquence ?– difficile, consommation++, chaleur++

• augmenter la complexité des processeurs– opérations spécialisées, logique (ex. prédiction de branchement),

cache, etc.– x2 logic → x1.4 performance (Pollack's rule)

!! vidéo !!

Page 10: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

10

Motivations pour le multi-cores

• Leviers pour augmenter les performances (cont.)– multiplier le nombre d'unités de calcul :

• parallélisme au niveau des instructions – out-of-order execution, pipelining

→ difficile (beaucoup de logique) et limité

• parallélisme au niveau des données (SIMD)– une seule instruction appliquée sur plusieurs registres– unités vectorielles : SSE, AVX, NEON, Cell SPE, (GPU)– efficace pour certaines applications, mais relativement

difficile à exploiter et reste limité

• parallélisme au niveau des threads– mettre plusieurs processeurs cote-à-cote

sur un même chip○ multi-core, many-core (>100)

– multi-processor : plusieurs chip sur une mêmecarte mère

un seulcoeur

Page 11: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

11

Motivations pour le multi-cores

• Plusieurs processeurs par circuits, plusieurs circuits par carte– réels gains théoriques:

• 2 « petits » processeurs → x1.8 perf

• 1 processeur 2 fois plus gros → x1.4 perf– consommation et dissipation de chaleur réduite

• N processeurs légèrement plus lents consomment autant qu'un seul rapide

• activation individuelle des processeurs– accès mémoires

• plusieurs CPU peuvent accéder en même temps à la mémoire

• permet d'augmenter la bande passante– même sans en réduire la latence

– simplicité

• plus simple de concevoir et fabriquer pleins de « petits » CPU simples,qu'un seul gros et complexe

→ améliore également la robustesse et absence de pannes/bugs

Page 12: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

12

Motivations pour le multi-cores

→ multi-core everywhere– CPU– GPU– super-calculateur– systèmes embarqués– smart-phones

embarqué (ex. Jetson)(4 cœurs CPU

+ 200-300 cœurs GPU)[↔ supercalculateur en 2000]

carte graphique(GPU :1000-3000 coeurs)

co-processeur dédié(GPU ou centaine de CPUs)

serveur

Page 13: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

13

mais...

• Programmer est difficile...

• Programmer parallèle est encore plus difficile !– trouver des tâches pouvant être exécuter en même temps– coordination entre les tâches, éviter les surcoûts...

Page 14: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

Architecture des CPUs

Page 15: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

15

CPU – Hiérarchie mémoire

regs

Cache - L1

Cache - L2

ALU

RAM (NUMA)

x100 bigger (90x90 floats) ; 1-4 cycles

x100 bigger (900x900 floats) ; 40-100 cycles

x1000 bigger ; ~400 cycles

small (8x8 floats) ; 1 cycle

Page 16: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

16

CPU - Parallélisme

• 3 niveaux de parallélisme :

1 – parallélisme au niveau des instructions

2 – SIMD – Single Instruction Multiple Data

3 – multi/many-cores – multi-threading

→ mécanismes complémentaires

Page 17: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

17

CPU – Parallélisme 1/3

• parallélisme au niveau des instructions– pipelining

• une opération = une unité de calcul (ex : addition)

• opération décomposée en plusieurs sous-taches– une sous-unité par sous-tache– 1 cycle par sous-tache

→ plusieurs opérations peuvent s'enchainer sur une même unité→ requière des instructions non dépendantes !

1op = 4 mini ops = 4 cycles

4 ops in 7 cycles !

time

a = a * b;c = c * d;e = e * f;g = g * h;

[démo]

Page 18: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

18

CPU – Parallélisme 1/3In-order / Out-of-order

• In-order processors– instruction fetch– attendre que les opérandes soient prêtes

• dépendances avec les opérations précédentes ou temps d'accès mémoire/caches– exécuter l'instruction par l'unité respective

• Out-of-orders processors– instruction fetch– mettre l'instruction dans une file d'attente– dès que les opérandes d'une des instructions de la file d'attente sont prêtes,

exécuter l'instruction par l'unité respective– couplée à la prédiction de branchement...

→ réduit les temps où le processeur est en attente

→ simplifie le travail du développeur/compilateur :)

→ requière des instructions non dépendantes

Page 19: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

19

CPU – Parallélisme 2/3

• SIMD → Single Instruction Multiple Data– Principe : exécuter la même opération sur plusieurs données en même temps– Jeux d'instructions vectoriels, ex :

• SSE (x86) : registres 128 bits (4 float, 2 double, 4 int)

• AVX (x86) : registres 256 bits (8 float, 4 double, 8 int)

• NEON (ARM) : registres 128 bits (4 float, 4 int)

• ...

4

-1

-6

2

-3

5

-2

4

* →

-12

-5

12

8

reg0 reg1 reg2

Page 20: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

20

CPU – Parallélisme 2/3SIMD

• Mise en oeuvre pratique, 3 possibilités :– vectorisation explicite via des fonctions « intrinsics » (pour les experts)– utiliser des bibliothèques tierces et optimisées– believe in your compiler !

• Nombreuses limitations :– réaliser des opérations intra-registres est difficile et très couteux– les données doivent être stockées séquentiellement en mémoire

• (voir slide suivant)

Page 21: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

21

CPU – Parallélisme 2/3SIMD

mémoire

fast(aligned)

slower(not aligned) don't be silly!

Page 22: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

22

CPU – Parallélisme 2/3SIMD

• Exemple de stockage pour des points 3D:

– Array of Structure (AoS)struct Vec3 { float x, y, z;} ;Vec3 points[100] ;

→ not SIMD friendly

– Structure of Arrays (SoA)struct Points { float x[100]; float y[100]; float z[100];};Points points;

[démo]

Page 23: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

23

CPU – Parallélisme 3/3

• multi/many-cores– Principe : chaque cœur exécute son propre flot d'instruction (=thread)

• thread = « processus léger »

• un thread par cœur à la fois

• assignation et ordonnancement par l'OS

• les threads communiquent via la mémoire partagée– mise en œuvre, ex :

• bibliothèques tierces

• via le compilateur et OpenMP(instrumentation du code)

– hyper-threading

• assigner deux threads sur unmême cœur

• exécution alternée au niveaudes instructions

• permet un meilleur tauxd'utilisation des unitées

• parfois contre-productifs !

PC

shared memory

CPU1 CPU2 CPUn...

Page 24: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

24

Peak performance

• Example : Intel i7 Quad CPU @ 2.6GHz (x86_64,AVX,FMA)

– pipelining/OOO → 2 * (mul + add) / cycle (cas idéal)– AVX → x 8 ops simple précision à la fois– multi-threading → x 4– fréquence → x 2.6G

→ peak performance: 332.8 GFlops

Page 25: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

26

Programmation multi-threadavec mémoire partagé

-

OpenMP

Page 26: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

27

Programmation multi-threads

• Très nombreuses approches, différents paradigmes– exemples de modèles :

• Google's « map-reduce » → divide and conquer

• Nvidia's data parallelism → big homogeneous array

• Erlang's fonctional programming → side-effect free

• OpenMP– intégré au compilateur– instrumentation manuelle du code

• en C/C++ via : #pragma omp ...– + ensembles de fonctions...– fournit différents outils et paradigmes

→ flexibilité

Page 27: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

28

OpenMP – premier exemple

• Exécuter un même bloc par plusieurs threads :

… et premières difficultés !– ici tous les threads accèdent de manière concurrentielle à la même ressource

(la sortie standard)– solution :

• autoriser un seul thread à la fois→ section critique via #pragma omp critical

#pragma omp parallel{ // on récupère le numéro du thread // (entre 0 et nombre_total_de_thread-1) int i = omp_get_thread_num();

cout << "Thread #" << i << " says hello!\n";}

[démo]

Page 28: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

29

OpenMP – 2ème exemple

• Paralléliser une boucle

– les m itérations de la boucles sont réparties entre les N threads

• une itération est exécutée une seule fois et par un seul thread

• un thread traite une seule itération à la fois– nombreuses stratégie d'affectation

• ex. : statique ou dynamique

• Exercice :– comment calculer le produit scalaire en un vecteur B et tous les éléments d'un

tableau

• ex, conversion d'une image RGB en Luminance, projection de m points sur un plan, etc.

→ quelles taches peuvent être effectuées en parallèle ?

#pragma omp parallel forfor(int i=0 ; i<m ; ++i){ ...}

[démo]

Page 29: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

30

OpenMP – 3ème exemple

• Exercice :– comment calculer la somme des éléments d'un tableau en parallèle ?

→ quelles taches peuvent être effectuées en parallèle ?

• Race condition

race condition(résultat différent en fonction

de l'ordre d'exécution)

correct behavior(critical section ou atomic)

Page 30: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

31

Atomic operations

• Principe– opération ou ensemble d'opérations s'exécutant sans pouvant être interrompues

• pour le reste du système : comme si son exécution était instantanée– nécessitent des mécanismes de synchronisation

misent en œuvre au niveau du matériel

• Exemples– Read-Write– Fetch-and-add

– Test-and-set

– Compare-and-swap

int test_and_set (int *val){ int old = *val; *val = 1; return old;}

x = x + a ;

Page 31: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

Comment paralléliserson code et ses algorithmes ?

• Dépend de nombreux facteurs– Nature du problème– Dimensions du problème– Matériel visé

→ Pas de solution universelle

→ Pas de solution automatique (compilateur)

• Acquérir de l'expérience– étudier des cas « simples »– retrouver des motifs connus au sein d'applications complexes

Page 32: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

Défis

• Trouver et exploiter la concurrence1 - identifier les taches indépendantes → approche hiérarchique2 - regrouper les taches → trouver la bonne granularité

→ regarder le problème sous un autre angle• Computational thinking (J. Wing)

• nombreuses façons de découper un même problème en taches

• Identifier et gérer les dépendances– Dépend du découpage !– Coordination entre les tâches (avoid races and deadlocks)

• éviter les attentes

Page 33: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

Défis

• Autres facteurs de performance :– Contrôler les surcouts

• limiter les échanges de données

• limiter les calculs supplémentaires– Équilibrer la charge de chaque unité– Saturation des ressources (bande-passante mémoire)

• Avant toute optimisation :– avoir un code qui fonctionne !– identifier les taches couteuses ! (on peut avoir des surprises)– penser à la complexité algorithmique !

Page 34: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

Qques motifs de parallélisationMap & Reduce

• « Map »– appliquer la même fonction à chacun des éléments d'un tableau– parallélisme évident : chaque élément peut être traité par un thread différent

• surjection de l'ensemble des M éléments → l'ensemble des N threads

• scheduling static– 1 thread ↔ un bloc de M/N éléments– ou 1 thread ↔ les éléments d'indices i*N

• scheduling dynamic– dès qu'un thread est libre, l'associer au premier élément non traité

• « Reduce » ou « Reduction »– réduire un tableau (ou sous-tableau) à une seule valeur

• Exemples : somme, produit, min, max, etc. (moyenne, calcul intégral,etc.)

• Si faible nombre de threads N : découper le problème en N sous problèmes puis réduire les N valeurs en 1 de manière séquentielle.→ généralisation à une approche hiérarchique

Page 35: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

Exemple : sampling et histogramme

• Approche séquentielle

RandomNumber

Generator

CDF 2D

MainThread

DestinationImage

for i=1..M { (x,y) = cdf.inverse(random(),random()); img(x,y) += incr;}

Page 36: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

Exemple : sampling et histogramme

• Multi-threading naif

RandomNumber

Generator

CDF 2D

DestinationImage

#pragma omp parallel forfor i=1..M { (x,y) = cdf.inverse(random(),random()); img(x,y) += incr;}

#T

#1

#2

Read-write→ critical section (bad)

Read-only

Read-onlymais variable d'étatinterne RW→ critical section (bad)

...

Page 37: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

Exemple : sampling et histogramme

• Multi-threading V1

RNG[1]

CDF 2D

DestinationImage

#pragma omp parallel forfor i=1..M { (x,y)=cdf.inverse(rng[tid].val(),rng[tid].val()); #pragma omp atomic img(x,y) += incr;}

#T

#1

#2

Read-write→ ou atomic (~OK)

→ 1 RNG/thread

RNG[2]

RNG[T]

......

Page 38: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

Exemple : sampling et histogramme

• Multi-threading V2

RNG[1]

CDF 2D

#T

#1

#2

→ 1 RNG/thread

RNG[2]

RNG[T]

Img[1]

Img[T]

Img[2]

...... ...Destination

Image∑

Cout mémoire :

Seconde passe→ parallel for

→ O ( N 2TT )

N 2TO (M /T ) , M≈N 2

Page 39: Programmation Parallèle sur CPU et GPU - labri.fr · • en C/C++ via : #pragma omp ... ... (résultat différent en fonction de l'ordre d'exécution) correct behavior (critical

Exemple : sampling et histogramme

• Multi-threading optimisé :

RNG[1]

CDF Y

#T

#1

#2RNG[2]

RNG[T]

...... ...

DestinationImage

Cout mémoire :

Découper l'image par thread→ nombreuses variantes→ ex : remplir ligne par ligne → meilleure cohérence des caches :) → nombre d'échantillons par ligne variable → scheduling dynamic

O (M /T )N T≪N 2

cpt[1]

cpt[2]

cpt[T]

cpt

Passe 1 : générer le nombre de samples par ligne (et par thread)

Passe 2 : sommerles compteursO ((N T )/T )

RNG[1]

#T

#1

#2RNG[2]

RNG[T]

......CDF X

Passe 3 : remplirligne par ligne,1 thread par ligne

O (M /T )