Comprendre les dimensions de la grille CUDA, les dimensions des blocs et l'organisation des threads (explication simple) [fermé]

Comment les threads sont-ils organisés pour être exécutés par un GPU?

134
demandé sur talonmies 2010-03-06 14:08:51

2 réponses

Matériel

Si un périphérique GPU a, par exemple, 4 unités multiprocessing, et ils peuvent exécuter 768 threads chacun: alors à un moment donné pas plus de 4*768 threads seront vraiment en cours d'exécution en parallèle (si vous avez prévu plus de threads, ils attendront leur tour).

Logiciel

Les Threads sont organisés en blocs. Un bloc est exécuté par une unité de multitraitement. Les threads d'un bloc peuvent être indentifiés (indexés) à l'aide d'index 1Dimension(x), 2dimensions (x,y) ou 3dim (x, y, z) mais dans tous les cas x y z

, Évidemment, si vous avez besoin de plus que ces 4*768 fils vous avez besoin de plus de 4 blocs. Les blocs peuvent également être indexés 1D, 2D ou 3D. il y a une file d'attente de blocs en attente d'entrer le GPU (parce que, dans notre exemple, le GPU a 4 multiprocesseurs et seulement 4 blocs sont en cours d'exécution simultanément).

Maintenant un cas simple: traitement d'un 512x512 image

Supposons qu'un thread traite un pixel (i, j).

Nous pouvons utiliser des blocs de 64 threads chacun. Ensuite, nous avons besoin de 512 * 512/64 = 4096 blocs (donc pour avoir 512x512 threads = 4096 * 64)

Il est courant d'organiser (pour faciliter l'indexation de l'image) les threads dans des blocs 2D ayant blockDim = 8 x 8 (Les 64 threads par bloc). Je préfère l'appeler threadsPerBlock.

dim3 threadsPerBlock(8, 8);  // 64 threads

Et 2D gridDim = 64 x 64 blocs (les 4096 blocs nécessaires). Je préfère l'appeler numBlocks.

dim3 numBlocks(imageWidth/threadsPerBlock.x,  /* for instance 512/8 = 64*/
              imageHeight/threadsPerBlock.y); 

Le noyau est lancé comme ceci:

myKernel <<<numBlocks,threadsPerBlock>>>( /* params for the kernel function */ );       

Enfin: il y aura quelque chose comme "une file d'attente de 4096 blocs", où un bloc attend d'être assigné à l'un des multiprocesseurs du GPU pour obtenir ses 64 threads exécutés.

Dans le noyau, le pixel (i, j) à traiter par un thread est calculé de la manière suivante:

uint i = (blockIdx.x * blockDim.x) + threadIdx.x;
uint j = (blockIdx.y * blockDim.y) + threadIdx.y;
252
répondu cibercitizen1 2017-04-28 09:27:09

Supposons un GPU 9800GT: 14 multiprocesseurs, chacun a 8 threadprocessors et warpsize est 32 ce qui signifie que chaque threadprocessor gère jusqu'à 32 threads. 14*8*32 = 3584 est le nombre maximum de threads actuels actuall.

Si vous exécutez ce noyau avec plus de 3584 threads (disons 4000 threads et ce n'est pas important de définir le bloc et la grille. gpu les traitera comme les mêmes):

func1();
__syncthreads();
func2();
__syncthreads();

, Puis l'ordre d'exécution de ces deux fonctions suit:

1.func1 est exécuté pour les 3584 premiers threads

2.func2 est exécuté pour les 3584 premiers threads

3.func1 est exécuté pour les threads restants

4.func2 est exécuté pour les threads restants

6
répondu Bizhan 2010-06-14 06:25:52