La carte graphique du gamer trouve un deuxième emploi
Une carte graphique conçue pour produire de meilleures explosions intéresse maintenant des chercheurs. Le détour devient compréhensible lorsqu’on compare le travail d’un CPU et celui d’un GPU.
Un CPU possède quelques cœurs très flexibles, de gros caches et une logique sophistiquée pour exécuter des branches différentes rapidement. Un GPU consacre davantage de transistors à de nombreuses unités de calcul plus simples. Il gagne lorsqu’on applique la même opération à beaucoup de données indépendantes : pixels, sommets ou éléments d’un vecteur.
Dans le pipeline graphique, le programme transforme les sommets, assemble les triangles, détermine les fragments visibles et calcule leur couleur avec des shaders. Des milliers de sommets ou pixels peuvent être traités en parallèle.
CPU : logique du jeu -> commandes de rendu
GPU : sommets -> triangles -> fragments -> shaders -> image
CUDA, rendu public par NVIDIA en 2006, permet de lancer un kernel général sur cette architecture. Pour additionner deux vecteurs, chaque fil traite un élément :
__global__ void addition(float *a, float *b, float *c) {
int i = blockIdx.x * blockDim.x + threadIdx.x;
c[i] = a[i] + b[i];
}
Le code paraît presque trop simple. La difficulté vient du déplacement et de l’organisation des données.
Le bus peut manger le gain
Les vecteurs vivent d’abord dans la mémoire principale. Il faut les copier vers la mémoire de la carte, lancer le kernel, puis ramener le résultat. Pour mille nombres, ce transfert et le lancement peuvent coûter plus cher que le calcul CPU. Pour des millions d’éléments et plusieurs opérations successives gardées sur le GPU, le parallélisme commence à payer.
Les fils sont exécutés par groupes. Si la moitié prend un if et l’autre le else, le groupe peut devoir parcourir les deux chemins, ce qui réduit le débit. Les accès mémoire dispersés produisent aussi beaucoup de transactions. Le meilleur problème GPU est régulier, massif et peu branché.
Un moteur de jeu vit sous une autre limite : le temps. À 60 images par seconde, simulation, préparation et rendu disposent de 16,7 ms. Le moteur simplifie les objets lointains, rejette ce qui est hors caméra et prépare les textures avant leur usage. Une moyenne de 16 ms ne suffit pas si une image prend 100 ms chaque seconde; le joueur ressent le blocage.
Le calcul général ajoute des questions de précision et de vérification. Certains GPU privilégient le flottant simple, suffisant pour beaucoup d’images mais pas pour tous les calculs scientifiques. Une erreur parallèle ou une condition de course peut produire un résultat plausible. Il faut comparer avec une version CPU sur un petit jeu connu, mesurer l’erreur numérique et vérifier plusieurs tailles.
Je ne travaille pas directement sur CUDA, mais je testerais un problème où la même formule s’applique à au moins quelques millions de valeurs. Je mesurerais séparément copie, calcul et retour. Le GPU n’est pas un CPU magique : il échange de la souplesse contre du débit. Le jeu a financé ce matériel parce qu’une image contient justement énormément de petits calculs semblables.