CUDA : [cours] [mise en pratique]
L'objectif du TD est de comparer les temps de calcul entre CPU et GPU pour calculer une courbe ou ensemble de Julia. On se réfère ici au chapitre 4 de CUDA par L'exemple.
Etant donnés deux nombres complexes, $c$ et $z_0$, on définit la suite $z_n$ par la relation de récurrence :
$z_{n+1} = z_n^2 + c$
Pour une valeur donnée de $c$, l'ensemble de Julia correspondant est la frontière de l'ensemble des valeurs initiales $z_0$ pour lesquelles la suite est bornée (l’ensemble de ces valeurs étant lui désigné comme l'ensemble de Julia rempli).
Voici une listes de valeurs à tester pour $c$:
Récupérer l'archive et étudier le code.
Le kernel qui est exécuté sur le CPU consiste à déterminer, pour chaque point de l'image de coordonnées complexes $(x + yi)$, s'il appartient à l'ensemble de Julia.
Elle détermine si un point de l'écran est dans l'ensemble en retournant la norme de $z$ sauf si celle-ci dépasse la valeur limite (NORM_THRESOLD = 4.0), on considère alors que la suite $z_n$ ne converge pas.
On centre les pixels sur le milieu de l'image et on les place dans l'intervalle $x=[-2.4 , +2.4]$ et $y=[-1.5 , +1.5]$.
on calcule 200 itérations de la fonction (soit 200 $z_i$), tout en vérifiant si l'équation diverge à chaque itération.
Réaliser une première implantation sur le GPU. On fera en sorte de créer une grille 2D de de la taille de l'image. Chaque bloc contient donc 1 seul thread qui se charge de calculer si le point de coordonnées $(threadIdx.x, threadIdx.y)$ appartient ou non à l'ensemble de Julia.
Modifier le fichier initial pour qu'on puisse réaliser l'exécution sur le GPU, puis comparer en terme de temps, les deux versions. On donnera un tableau comparatif des temps pour les valeurs suivantes de l'image :
On s'arrange pour que la grille soit composée de moins de blocs qui contiennent plus de thread (grille 2D de blocs 2D). Notez l'amélioration obtenue par rapport à la première version GPU et donner les temps comparatifs pour les tailles d'images de l'exercice précédent ainsi que pour :
Déterminer la meilleure configuration possible pour votre GPU. Pour cela faire un test de peformance avec différentes tailles de blocs et comparer les temps GPU.
On fixera les variables suivantes pour récupérer le résultat dans le fichier julia.log
export CUDA_PROFILE=1
export CUDA_PROFILE_LOG=julia.log
export CUDA_PROFILE_CSV=1
ou alors on utilisera nvprof.
Voici à présent plusieurs résultats comparatifs entre CPU et carte graphique pour une représentation en simple précision et double précision.
hardware | dim | CPU | CPU (4 threads) | CPU (8 threads) | GPU |
i5-4570 @ 3.20GHz, GeForce GTX 770 | 256 | 196 | 193 | 194 | 2 |
i5-4570 @ 3.20GHz, GeForce GTX 770 | 512 | 775 | 775 | 775 | 6 |
i5-4570 @ 3.20GHz, GeForce GTX 770 | 1024 | 3115 | 3169 | 3203 | 19 |
i5-4570 @ 3.20GHz, GeForce GTX 770 | 2048 | 12688 | 12808 | 12473 | 64 |
i5-4570 @ 3.20GHz, GeForce GTX 770 | 4096 | 49763 | 49803 | 49728 | 230 |
i5-3570K @ 3.40GHz, GeForce GTX 560 Ti | 256 | 221 | 83 | 75 | 5 |
i5-3570K @ 3.40GHz, GeForce GTX 560 Ti | 512 | 884 | 332 | 283 | 18 |
i5-3570K @ 3.40GHz, GeForce GTX 560 Ti | 1024 | 3538 | 1327 | 1045 | 63 |
i5-3570K @ 3.40GHz, GeForce GTX 560 Ti | 2048 | 14126 | 5303 | 4514 | 210 |
i5-3570K @ 3.40GHz, GeForce GTX 560 Ti | 4096 | 56482 | 21207 | 16526 | 756 |
Xeon E5-2670 v2 @ 2.50GHz, Tesla K20m | 256 | 829 | 326 | 218 | 3 |
Xeon E5-2670 v2 @ 2.50GHz, Tesla K20m | 512 | 3314 | 1334 | 781 | 10 |
Xeon E5-2670 v2 @ 2.50GHz, Tesla K20m | 1024 | 13262 | 5094 | 3080 | 30 |
Xeon E5-2670 v2 @ 2.50GHz, Tesla K20m | 2048 | 52952 | 19881 | 12211 | 114 |
Xeon E5-2670 v2 @ 2.50GHz, Tesla K20m | 4096 | 212095 | 79500 | 48853 | 591 |
i7-4790 CPU @ 3.60GHz, GeForce GTX 660 | 256 | 175 | 68 | 45 | 3 |
i7-4790 CPU @ 3.60GHz, GeForce GTX 660 | 512 | 700 | 266 | 169 | 8 |
i7-4790 CPU @ 3.60GHz, GeForce GTX 660 | 1024 | 2799 | 1073 | 675 | 28 |
i7-4790 CPU @ 3.60GHz, GeForce GTX 660 | 2048 | 11219 | 4287 | 2657 | 98 |
i7-4790 CPU @ 3.60GHz, GeForce GTX 660 | 4096 | 44613 | 17009 | 10637 | 346 |
i7-4790 CPU @ 3.60GHz, GeForce GTX 970 | 256 | 174 | 68 | 44 | 2 |
i7-4790 CPU @ 3.60GHz, GeForce GTX 970 | 512 | 697 | 267 | 167 | 5 |
i7-4790 CPU @ 3.60GHz, GeForce GTX 970 | 1024 | 2797 | 1071 | 665 | 16 |
i7-4790 CPU @ 3.60GHz, GeForce GTX 970 | 2048 | 11173 | 4297 | 2668 | 59 |
i7-4790 CPU @ 3.60GHz, GeForce GTX 970 | 4096 | 44705 | 17209 | 10484 | 204 |
hardware | dim | CPU | CPU (4 threads) | CPU (8 threads) | GPU |
i5-4570 CPU @ 3.20GHz, GeForce GTX 770 | 256 | 195 | 88 | 65 | 24 |
i5-4570 CPU @ 3.20GHz, GeForce GTX 770 | 512 | 791 | 357 | 250 | 67 |
i5-4570 CPU @ 3.20GHz, GeForce GTX 770 | 1024 | 3140 | 1312 | 1034 | 218 |
i5-4570 CPU @ 3.20GHz, GeForce GTX 770 | 2048 | 12417 | 4774 | 3824 | 702 |
i5-4570 CPU @ 3.20GHz, GeForce GTX 770 | 4096 | 50733 | 20532 | 16305 | 2569 |
i5-3570K @ 3.40GHz, GeForce GTX 560 Ti | 256 | 221 | 84 | 67 | 30 |
i5-3570K @ 3.40GHz, GeForce GTX 560 Ti | 512 | 884 | 332 | 273 | 84 |
i5-3570K @ 3.40GHz, GeForce GTX 560 Ti | 1024 | 3537 | 1327 | 1097 | 277 |
i5-3570K @ 3.40GHz, GeForce GTX 560 Ti | 2048 | 14121 | 5304 | 4257 | 967 |
i5-3570K @ 3.40GHz, GeForce GTX 560 Ti | 4096 | 56465 | 21193 | 17258 | 3514 |
Xeon E5-2670 v2 @ 2.50GHz, Tesla K20m | 256 | 256 | 98 | 61 | 4 |
Xeon E5-2670 v2 @ 2.50GHz, Tesla K20m | 512 | 1033 | 388 | 238 | 17 |
Xeon E5-2670 v2 @ 2.50GHz, Tesla K20m | 1024 | 4135 | 1616 | 953 | 41 |
Xeon E5-2670 v2 @ 2.50GHz, Tesla K20m | 2048 | 16504 | 6192 | 3799 | 159 |
Xeon E5-2670 v2 @ 2.50GHz, Tesla K20m | 4096 | 66000 | 24762 | 15194 | 700 |
i7-4790 CPU @ 3.60GHz, GeForce GTX 660 | 256 | 177 | 70 | 45 | 29 |
i7-4790 CPU @ 3.60GHz, GeForce GTX 660 | 512 | 711 | 271 | 172 | 98 |
i7-4790 CPU @ 3.60GHz, GeForce GTX 660 | 1024 | 2855 | 1098 | 693 | 314 |
i7-4790 CPU @ 3.60GHz, GeForce GTX 660 | 2048 | 11344 | 4320 | 2696 | 1001 |
i7-4790 CPU @ 3.60GHz, GeForce GTX 660 | 4096 | 45309 | 17509 | 10831 | 3656 |
i7-4790 CPU @ 3.60GHz, GeForce GTX 970 | 256 | 177 | 69 | 45 | 28 |
i7-4790 CPU @ 3.60GHz, GeForce GTX 970 | 512 | 708 | 274 | 172 | 69 |
i7-4790 CPU @ 3.60GHz, GeForce GTX 970 | 1024 | 2846 | 1084 | 693 | 214 |
i7-4790 CPU @ 3.60GHz, GeForce GTX 970 | 2048 | 11378 | 4355 | 2753 | 776 |
i7-4790 CPU @ 3.60GHz, GeForce GTX 970 | 4096 | 45407 | 17501 | 10811 | 2670 |
Ces tableaux appellent quelques commentaires :
Exemple avec Tesla K20m : meilleur temps 608 ms avec un bloc de 16 x 16
block size | time (ms) | occupancy |
2 | 12122 | 0.250 |
3 | 5794 | 0.250 |
4 | 3514 | 0.250 |
5 | 2378 | 0.250 |
6 | 1438 | 0.500 |
7 | 1131 | 0.500 |
8 | 931 | 0.500 |
9 | 929 | 0.750 |
10 | 718 | 1.000 |
11 | 655 | 1.000 |
12 | 691 | 0.938 |
13 | 706 | 0.938 |
14 | 756 | 0.984 |
15 | 641 | 1.000 |
16 | 608 | 1.000 |
17 | 683 | 0.938 |
18 | 705 | 0.859 |
19 | 637 | 0.938 |
20 | 702 | 0.812 |
21 | 682 | 0.875 |
22 | 637 | 1.000 |
23 | 707 | 0.797 |
24 | 747 | 0.844 |
25 | 650 | 0.938 |
26 | 907 | 0.688 |
27 | 791 | 0.719 |
28 | 725 | 0.781 |
29 | 693 | 0.844 |
30 | 712 | 0.906 |
31 | 658 | 0.969 |
32 | 654 | 1.000 |