Note : ce cours représente une brève introduction à CUDA. On pourra lire les différents ouvrages traitant du sujet [1, 2, 3] pour se familiariser avec les fonctionnalités avancées de CUDA.
CUDA is a parallel computing platform and programming model invented by NVIDIA. It enables dramatic increases in computing performance by harnessing the power of the graphics processing unit (GPU). NVIDIA provides a complete toolkit for programming on the CUDA architecture, supporting standard computing languages such as C, C++ and Fortran (NVidia)
Ici le verbe harness peut être traduit par : en exploitant au mieux.
Depuis l'invention du microprocesseur (CPU = Central Processing Unit) par Intel en 1971, les circuits intégrés ont connu de nombreuses améliorations qui ont concourru à l'augmentation de leurs performances :
Cependant, en terme de parallèlisme, même si on dispose de plusieurs coeurs, ceux-ci exécutent en général des programmes différents, on est dans un modèle MIMD (Multiple Instructions, Multiple Data). Seules les unités dédiées (SSE, AVX) permettent de faire du calcul parallèle, mais on parle ici de circuits vectoriels capables de traiter 4 réels simple précision dans le cas du SSE4.2.
L'utilisation de plusieurs coeurs de microprocesseurs, ou de plusieurs microprocesseurs pour la programmation en parallèle est qualifiée de programmation multi-core.
Exemple d'application maximum de parcimonie
En parallèle des CPU, les GPU (Graphics Processing Unit) circuits initialement conçus pour l'affichage graphique (notamment la 2D et dans une plus large mesure la 3D), ont connu un essor fulgurant. La rivalité des constructeurs NVidia et ATI (racheté par AMD) a été bénéfique et elle a mené à l'évolution des GPU vers des circuits dédiés au calcul hautement parallèle. En fonction du GPU on est capable de traiter plusieurs centaines ou milliers de réels simple précision en parallèle.
Comparaison multi et many core
L'utilisation d'un GPU pour le calcul parallèle est qualifiée de programmation many-core et correspond à du SIMD (Single Instruction, Multiple Data) ou plutôt à ce que les constructeurs appellent du SIMT (Single Instruction, Multiple Thread).
Notons qu'en 2009, la puissance de calcul d'un CPU était d'environ 100 GFlops alors que celle d'un GPU était 1 TFlops, soit 10 fois plus importante.
Les graphiques suivants peuvent être trouvés ici pour des versions plus récentes.
Evolution des performances en GFlops des CPU et GPU
(Source: Nvidia CUDA Programming Guide)
Evolution de la Bande passante mémoire en Go/s des CPU et GPU
(Source: Nvidia CUDA Programming Guide)
CPU | GPU | |
concepteur | Intel | NVIDIA |
modèle | Core i7 920 | GTX 280 |
date de lancement | Juin 2008 | Novembre 2008 |
prix (dollars) | 260 | 260 |
fréquence | 2.66 GHz | 1.3 GHz |
cores | 4 | 240 |
threads | 8 | 23040 |
GFlops | 64 | 933 |
BP mémoire Go/s | 31.8 | 141.7 |
TDP | 130W | 236W |
GFlops/W | 0.49 | 3.95 |
Dans le tableau comparatif précédent, si on désire obtenir la même puissance de calcul qu'une carte graphique grâce à un CPU, on devra utiliser $933 / 64 = 14.57$ soit environ 15 CPU, ce qui représente :
Les GPU ont évolué de manière drastique en passant des stations de travail très onéreuses des années 80 (\$50.000) à des périphériques PC abordables de l'ordre de \$200 à la fin des années 1990.
début 1980 | fin 1990 | |
pixels/s | 5 x 10^7 | 10^9 |
vertex/s | 10^5 | 10^7 |
L'évolution des performances est due à deux facteurs:
Au final, on est passé en 30 ans d'un simple pipeline traitant des structures en fil de fer à une conception hautement parallèle composée de plusieurs pipelines capables de produire le rendu de scènes 3D.
On rappelle que le but d'une carte graphique est de produire une image (ensemble 2D de pixels avec couleurs) à partir d'une scène 3D ou les objets sont modélisés par des triangles (composés de 3 sommets) auxquels on applique des textures et des effets de lumière, ceci en fonction de l'angle de vue de l'utilisateur dans la scène et des sources de lumière.
Du début des années 1980 à la fin des années 1990, les GPU étaient conçus comme des pipelines dotés de fonctions graphiques dédiées configurables. Les données (vertex) en provenance du CPU sont traitées par le pipeline graphique.
A partir de 2001, l'arrivée du GPU NVidia GeForce 3 représente l'ouverture aux programmeurs du pipeline graphique, notamment la partie VS/T&L. La tendance générale vers une unification des fonctionnalités des différentes étapes de traitement se poursuit également avec les différentes versions de DirectX (version 8 à 10).
Microsoft DirectX est une collection de bibliothèques destinées à la programmation d’applications multimédia, plus particulièrement de jeux ou de programmes faisant intervenir de la vidéo, sur les plates-formes Microsoft (Xbox, systèmes d’exploitation Windows).
(Wikipedia)
On passe alors d'un pipeline pré-programmé à un pipeline programmable dont la logique a été extraite en amont des traitements. On peut faire une analogie avec la construction automobile et les différents niveaux de finition. Plutôt que d'avoir autant de chaînes de productions que de finitions, on crée une seule chaîne. Un modèle de qualité supérieure engendrera plus d'étapes de traitements sur chaîne.
Avec l'évolution du matériel des GPU et l'ouverture progressive du pipeline de traitement, certains se sont aperçus qu'il était possible d'utiliser le GPU pour effectuer des calculs parallèles, ceci à partir de la version 9 de DirectX. Cependant, il s'agissait d'un véritable tour de force car l'API de DirectX 9 était encore nettement orientée traitements graphiques.
Le programmeur devait alors coder ses calculs sous forme de traitement de type pixel shader, les données en entrée étaient stockées dans des images de textures et les données en sorties devaient être transformées sous forme de pixels générés par l'opération raster. De nombreux autres problèmes devaient être réglés (cf. [1] page 31).
On qualifie cette première étape d'utilisation des fonctionnalités graphiques des GPU pour le calcul parallèle de GPGPU : General-Purpose computing on GPU, par opposition au GPU computing, où le GPU est dédié au calcul parallèle.
C'est à partir du développement de l'architecture Tesla (2007) que NVidia a réalisé l'utilité de pouvoir modéliser et utiliser le GPU comme un CPU. Attention : ne pas confondre l'architecture Tesla et les cartes Tesla du même constructeur, voir ci-après dans ce chapitre.
Le code écrit en CUDA peut être infime mais apporter un gain de performance impressionnant
CPU | Puissance de crête | TDP |
Intel Pentium 4 - 2.8 Ghz - 1 coeur - x86 | 2.7 GFlops | 70 W |
Intel Centrino Duo - 1.66 Ghz - 2 coeurs - x86 | 3.1 GFlops | 30 W |
Intel Xeon 5410 - 2.33 Ghz - 4 coeurs - x64 | 9,5 GFlops | 100 W |
Intel Core I7 980x - 3.33 Ghz - 6 coeurs - x64 | 20 GFlops | 130 W |
AMD Athlon 64 x2 - 3 Ghz - 2 cœurs - x64 | 5,9 GFlops | 65 W |
AMD Phenom II x6 - 3.0 Ghz - 6 cœurs - x64 | 17,8 GFlops | 100 W |
GPU | Puissance de crête | TDP |
NVidia 9800 GT - 112 cœurs - 600 Mhz | 370 GFlops | 230 W |
NVidia GT240 - 96 coeurs - 550 Mhz | 260 GFlops | 180 W |
NVidia GTX 285 - 240 cœurs - 648 Mhz | 700 GFlops | 370 W |
NVidia GTX 480 - 480 cœurs - 700 Mhz | 1350 GFlops | 410 W |
ATI HD 3870 - 320 cœurs - 775 Mhz | 490 GFlops | 240 W |
ATI HD 4890 - 800 cœurs - 850 Mhz | 1360 GFlops | 290 W |
ATI HD 5970 - 3200 cœurs - 725 Mhz | 4640 GFlops | 430 W |
Le calcul haute performance a pour objectif d'atteindre les plus hautes performances possibles en terme de calcul avec des technologies de pointe. Les machines qui résultent de la conception basée sur ce principe sont qualifiées de superordinateurs ou supercalculateurs (super computers). L'activité scientifique chargée de concevoir et programmer ces superordinateurs est appelée Calcul Haute Performance ou HPC en anglais pour High Performance Computing.
Les organismes de recherche civils et militaires comptent parmi les utilisateurs de superordinateurs qui sont destinés aux principaux domaines suivants :
La puissance des supercalculateurs est exprimée en Flops (Floating Point Operations per Second) car la plupart des applications susnommées utilisent les nombres rééls pour représenter des coordonnées dans l'espace, des distances, des forces, des énergies, ... On utilise le test LINPACK (Résolution de systèmes d'équations linéaires) pour évaluer la puissance des supercalculateurs.
Rappelons que l'ASCI Red (1996--2006) d'Intel fut le premier à atteindre en 1997 la puissance d'1 PFlops en utilisant près de 9300 Intel Pentium Pro 200 Mhz.
Le Tianhe-1 (Voie Lactée) est un supercalculateur du National Supercomputing Center, à Tianjin en Chine. En octobre 2010, une version améliorée de la machine (Tianhe-1A) est devenue le supercalculateur le plus rapide au monde : Processeurs Intel Xeon (14366) + GPU NVIDIA Tesla M2050 (7166).
Avec le Tianhe-2 la chine ambitionne de passer le cap des 100 PFlops d'ici à trois ans, puis d'accélérer encore pour dépasser le seuil hautement symbolique de l'exaflops (1 EFlops = 1 000 PFlops = $10^{18}$ calculs en virgule flottante à la seconde) d'ici 2018. (source Tomshardware.com).
Octobre 2012, Le Titan (Oak Ridge National Laboratory, USA, Tennessee) : On passe donc à 18 688 cartes Telsa K20 (a priori), soit 28 704 768 unités de calcul sur le GPU, et 18 688 Opteron 6274, des modèles « Bulldozer » dotés de 16 cores (plus exactement 8 cores et 16 modules), soit 299 008 threads. Il est doté de 710 To de mémoire et sa consommation devrait être de 9 mégawatts environ, soit à peine plus que l'itération précédente du supercalculateur — c'est une simple mise à jour — pour une puissance théorique multipliée par 10 environ.
La machine offre une puissance théorique qui dépassera 20 pétaflops et environ 90 % de la puissance de calcul vient des cartes Tesla (source Tomshardware.com, voir également l'article d'Anandtech)
Tesla dévoile le nouveau superordinateur Dojo
Le site top500.org recense les superordinateurs les plus puissants. En Juin 2015, le superordinateur le plus puissant est le Tianhe-2 avec une puissance de 33,86 petaflop/s pour LINPACK.
Le site green500.org recense quant à lui les superordinateurs consommant le moins d'énergie.
De plus en plus de superordinateurs utilisent de GPU compatibles CUDA en raison d'une consommation énergétique beaucoup plus faible, pour un coût de revient plus faible et une puissance de calcul supérieure à celle des CPU.
On distingue 3 types de produits pour des usages différents compatibles CUDA :
A partir de la série GeForce 400 qui correspond à la 11ème génération de GPU GeForce, les chipsets sont identifiés par la lettre qui correspond à l'architecture suivi d'un numéro à 3 chiffres :
Le problème est que pour une architecture donnée (ex. Fermi) il existe plusieurs sous-architectures (GF100, GF104, ...).
Les GeForce sont généralement connectées au travers du bus PCI Express 1.0, 2.0 ou 3.0 ayant un débit d'environ 16 Go/s.
Caractéristiques | PCI Express 1.0 | PCI Express 2.0 | PCI Express 3.0 | PCI Express 4.0 |
bande passante (GT/s) | 2.5 | 5 | 8 | 16 |
débit par ligne (Mo/s) | 250 | 500 | 984.6 | 1969.2 |
débit pour 16 lignes (Go/s) | 4 | 8 | 15.754 | 31.508 |
Par exemple pour le PCI Express 3.0, les données sont encodées sur 128 bits + 2 bits pour le contrôle, (alors que dans les versions précédentes on utilisait un encodage 8/10 bits). On parle d'encodage 128b/130b. Dans ce cas on perd 1.54% ( $(130-128)/130×100 = 1.538 ≈ 1.54$ ).
La bande passante est donc de $8000/8×(100-1.54)/100 = 984.60$ Mo/s
Sur certaines cartes mères, par exemple celles basées sur le chipset Z87 (Haswell) ou Z77 (Ivy Bridge), on dispose de plusieurs modes :
Avec une seule carte on utilise 16 lignes PCI Express, mais avec 2 cartes on utilise 8 lignes par carte.
Autre exemple avec la carte MSI 287M-G43, on dispose de :
Il faut connecter la carte la plus puissante sur le port PCI Express 3.0
Pour le Calcul Haute Performance NVidia propose sa gamme de produits Tesla qui possède des avantages par rapport aux cartes graphiques dédiées aux jeux. Voilà ce que nous dit NVidia :
Voici quelques extraits d'un article de The Platform.net :
While the CUDA programming environment for GPU offload was invented in 2006 for the GeForce 8800 graphics cards, the concept of a separate Tesla GPU coprocessor aimed at supercomputing clusters did not happen until two years later with the launch of the Tesla C870 and D870 devices, which offered single precision floating point processing.
... the Tesla line is now at an annual revenue run rate of several hundred million dollars and grew at around 50 percent in the last fiscal year for Nvidia (2015), driven by strong adoption by both HPC and hyperscale organizations. ... New at the GTC 2015 event this week was Huang divulging that Nvidia has shipped a cumulative 450,000 Tesla coprocessors, an increase of 7.5 percent from 2008. (Cumulative CUDA downloads have increased by a factor of 20X, and that is because CUDA works on all Nvidia GPUs, not just Tesla coprocessors.)
Exemple
NVidia propose également des stations de calcul haute performance :
Composant | Caractérisique |
Carte mère | Dual socket LGA 1366, chipset Intel 5520/ICH10R |
Processeurs | 2 x Intel Xeon 6 Core X5670 (2.93Ghz, 12Mo de cache, 1333MHz, 95W) |
Mémoire | 24Go DDR3 1333Mhz ECC REG - Extensible à 64Go |
Disques durs | 2 x 1To SATA II - 64Mo |
GPU | 4 x NVIDIA Tesla C2075, 6Go de mémoire DDR5, 1 x interface PCIe x16 2.0 |
Système d'exploitation | Linux Fedora |
Exemple chez Transtec d'un noeud CUDA 3230 Compute Node Système Rack 1U :
Composant | Caractérisique |
Processeur | 1 x Intel Xeon 6 Core E5-2603v3 (1.6 Ghz, 15 Mo de cache L3, 1333MHz, 85W) |
Mémoire | 8 GB DDR4 DIMM, 2133 MHz, registered, ECC |
Disques durs | 1 x 500 Go SATA, 7200 tr/min |
GPU | 1 Tesla K80 24 Go |
Total | 15997 € |
Évolution du DGX-1 doté de puces à architecture Pascal, le DGX-1V embarque 8 cartes Tesla V100 basées sur l'architecture Volta. Les caractéristiques sont les suivantes :
Carte graphique | Prix € | SP GFlops | DP Glops |
PNY Tesla M60 16 Go | 7122 | 9650 | 300 |
PNY Quadro M6000 12 Go | 5633 | 6070 | 190 |
MSI GTX 1080 Ti 11 Go | 769 | 16609 | 332 |
MSI GTX 1080 Gaming 8 Go | 579 | 8228 | 257 |
Asus GTX 1070 STRIX 8 Go | 485 | 5783 | 181 |
Carte graphique | Prix € | SP GFlops | DP Glops |
PNY GeForce GTX 970 4 Go GDDR5 | 309 | 3494 | 109 |
Gigabyte GeForce GTX 980 4 Go GDDR5 | 559 | 4612 | 144 |
PNY Tesla K20 5 Go | 4709 | 4100 | 1173 |
PNY Tesla K40 12 Go | 3507 | 5364 | 1430 |
PNY Quadro K4000 3 Go | 5610 | 1626 | - |
NVidia Quadro K6000 12 Go | 5463 | 5196 | 1732 |
Exercice: comparer le rapport performance / prix entre GTX 970 et Tesla K40.
Carte graphique | Prix € |
PNY GeForce GTX 580 1536Mo GDDR5 | 417 |
PNY GeForce GTX 680 2Go GDDR5 | 499 |
PNY Tesla C2050 | 1874 |
PNY Quadro 5000 2.5 Go | 4969 |
Année | 2008 | 2015 | Gain |
GPUs vendus | 100 millions | 600 millions | x 6 |
Superordinateurs | 1 | 75 | x 75 |
Cours universitaires | 60 | 840 | x 14 |
papiers académiques | 4.000 | 50.000 | x 12.5 |
NVidia diffuse une newsletter relative à CUDA : CUDA Week in Review. Les sujets abordés sont les suivants :
On trouvera également la liste des GPUs compatibles CUDA ainsi que la NVidia Developer Zone.
Etudes de cas de NVidia
Il existe un utilitaire linpack lié à la MKL (Math Kernel Library) d'Intel qui permet de connaître la puissance en GFlops de votre processeur Intel (Linux, Windows, MacOS) : Intel MKL Linpack
Intel® Optimized LINPACK Benchmark is a generalization of the LINPACK 1000 benchmark. It solves a dense (real*8) system of linear equations (Ax=b), measures the amount of time it takes to factor and solve the system, converts that time into a performance rate, and tests the results for accuracy. The generalization is in the number of equations (N) it can solve, which is not limited to 1000. It uses partial pivoting to assure the accuracy of the results. source: Intel
./linpack_11.0.0/benchmarks/linpack/runme_xeon32
Intel(R) Optimized LINPACK Benchmark data
Current date/time: Tue Oct 16 14:35:06 2012
CPU frequency: 3.390 GHz
Number of CPUs: 1
Number of cores: 4
Number of threads: 4
Performance Summary (GFlops)
Size LDA Align. Average Maximal
15000 15000 4 75.3443 75.3443
14000 14008 4 77.2016 77.2368
13000 13000 4 75.2261 76.5220
12000 12008 4 72.3286 76.1669
11000 11000 4 71.7737 74.3548
10000 10008 4 75.4813 75.7207
8000 8008 4 67.0813 67.9952
6000 6008 4 71.4119 71.5401
1000 1000 4 49.5919 53.2004
Autres résultats :
CPU | Freq. (Ghz) | Cores | Threads | MaxPeak (GFlops) |
Core i5-4570 | 3.20 | 4 | 4 | 71.43 |
Core i7-2600 | 3.40 | 4 | 8 | 81.15 |
Core i5 3570k | 3.40 | 4 | 4 | 77.20 |
Core i7 860 | 2.80 | 4 | 8 | 38.70 |
Core2 Quad Q9300 | 2.50 | 4 | 8 | 34.27 |
Core 2 Duo E8400 | 3.00 | 2 | 2 | 20.33 |
Core i7-2760QM | 2.40 | 4 | 8 | 59.28 |
CPU | Freq. (Ghz) | Cores | Threads | MaxPeak (GFlops) |
Core i5-4570 | 3.20 | 4 | 4 | 118.06 |
Core i7-2760QM | 2.40 | 4 | 8 | 66.66 |
On note que pour le Core i5-4570, le fait d'être en 64 bits augmente les performances.
Calcul récursif Fibonacci : soit une matrice d'entiers de dimension $N$ calculer $m[i,j] = fib(m[i,j])$, telle que fib est une fonction récursive.
N | CPU | CPU (4 coeurs) | GPU | Accélération |
1024 | 0.178 | 0.071 | 0.016 | x4.43 |
2048 | 0.692 | 0.252 | 0.065 | x3.87 |
4096 | 2.720 | 0.806 | 0.249 | x3.23 |
8192 | 10.945 | 3.375 | 0.945 | x3.57 |
Note: OpenMP ou OMP (Open Multi-Processing) est une interface de programmation pour le calcul parallèle sur architecture à mémoire partagée.
soit une matrice d'entiers de dimension $N$, déterminer si $m[i,j]$ est un nombre premier.
CPU/GPU | N | tCPU | tCPU (4 coeurs) | tGPU | Accélération |
i5-4570 / GTX 770 | 1024 | 0.261 | 0.092 | 0.012 | x7.66 |
i5-4570 / GTX 770 | 2048 | 1.892 | 0.653 | 0.091 | x7.17 |
i5-4570 / GTX 770 | 4096 | 13.785 | 4.787 | 0.713 | x6.71 |
i5-3570K / GTX 560 Ti | 1024 | 0.284 | 0.092 | 0.030 | x3.06 |
i5-3570K / GTX 560 Ti | 2048 | 2.002 | 0.666 | 0.238 | x2.79 |
i5-3570K / GTX 560 Ti | 4096 | 14.661 | 4.860 | 1.862 | x2.61 |
i7-4790 / GTX 970 | 1024 | 0.241 | 0.080 | 0.012 | x6.66 |
i7-4790 / GTX 970 | 2048 | 1.699 | 0.584 | 0.078 | x7.48 |
i7-4790 / GTX 970 | 4096 | 12.401 | 4.247 | 0.610 | x6.96 |
Calcul d'image pour courbe de Julia (cf TD)
Methode | Temp (s)s | Accélération |
CPU (1 coeur) | 30.535 | - |
CPU (4 coeurs, OpenMP) | 8.355 | x3.65 |
GPU (G=512x512, B=16x16) | 0.736 | x41.48 |
Cf cours INRA interopérabilité avec Python.
Le SDK (Standard Development Kit) CUDA est généralement installé dans le répertoire /usr/local/cuda. Ce répertoire contient notamment les sous répertoires :
Se placer dans le répertoire /usr/local/cuda/samples et taper make pour générer les exécutables des exemples.
Une fois compilés, lancer :
cd /usr/local/cuda/samples
1_Utilities/deviceQuery/deviceQuery
1_Utilities/bandwidthTest/bandwidthTest
nvidia-smi
L'utilitaire en ligne de commande nvidia-smi donne des informations sur les cartes présentes :
\$ nvidia-smi
Wed Sep 27 08:58:29 2017
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 378.13 Driver Version: 378.13 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 GeForce GTX 970 Off | 0000:01:00.0 On | N/A |
| 1% 53C P0 46W / 200W | 246MiB / 4034MiB | 0% Default |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: GPU Memory |
| GPU PID Type Process name Usage |
|=============================================================================|
| 0 1345 G /usr/lib/xorg/Xorg 166MiB |
| 0 2586 G compiz 34MiB |
| 0 3417 G ...s-passed-by-fd --v8-snapshot-passed-by-fd 42MiB |
+-----------------------------------------------------------------------------+
L'utilitaire graphique nvidia-settings est généralement plus intéressant et permet de régler la puissance du GPU: