48 votes

Modèle CUDA - qu'est-ce que la taille de la distorsion ?

Quelle est la relation entre la taille maximale du groupe de travail et la taille de la chaîne de traitement ? Supposons que mon appareil dispose de 240 processeurs de streaming CUDA (SP) et qu'il renvoie les informations suivantes -

CL_DEVICE_MAX_COMPUTE_UNITS : 30

CL_DEVICE_MAX_WORK_ITEM_SIZES : 512 / 512 / 64

CL_DEVICE_MAX_WORK_GROUP_SIZE : 512

CL_NV_DEVICE_WARP_SIZE : 32

Cela signifie qu'il y a huit SP par multiprocesseur de streaming (c'est-à-dire par unité de calcul). Quel est le lien entre la taille de la chaîne = 32 et ces chiffres ?

123voto

M. Tibbits Points 3867

Réponse directe : La taille de la chaîne est le nombre de threads dans une chaîne, qui est une sous-division utilisée dans l'implémentation matérielle pour fusionner l'accès à la mémoire et l'envoi des instructions.

Lecture suggérée :

Comme @Matias l'a mentionné, je lirais la Guide des meilleures pratiques CUDA C (vous devrez faire défiler la liste jusqu'en bas). Il peut être utile de regarder le tableau de l'annexe G.1 à la page 164.

Explication :

CUDA est un langage qui permet le parallélisme à deux niveaux. Vous avez des threads et des blocs de threads. Ceci est particulièrement évident lorsque vous exécutez un noyau ; vous devez spécifier la taille de chaque bloc de threads et le nombre de blocs de threads entre les <<< >>> qui précèdent les paramètres du noyau.

Ce que CUDA ne dit pas, c'est que les choses se passent en réalité à quatre niveaux, et non à deux. En arrière-plan, votre bloc de threads est en fait divisé en sous-blocs appelés "warps". Voici une brève métaphore pour vous aider à comprendre ce qui se passe réellement :

Brève métaphore :

Imaginez que vous êtes un éducateur/chercheur/politicien qui s'intéresse aux capacités mathématiques actuelles des élèves de terminale. Votre plan consiste à faire passer un test à 10 240 élèves, mais vous ne pouvez pas les réunir tous dans un stade de football ou autre et leur faire passer le test. Il est plus facile de subdiviser (paralléliser) votre collecte de données - vous vous rendez donc dans 20 lycées différents et demandez à 512 de leurs élèves de terminale de passer le test de mathématiques.

Le nombre de lycées, 20, est analogue au nombre de "blocs" / "nombre de blocs de fils". Le nombre de terminales, 512, est analogue au nombre de fils dans chaque bloc ou "fils par bloc".

Vous collectez vos données et c'est tout ce qui vous intéresse. Ce que vous ne saviez pas (et n'avez pas vraiment ) est que chaque école est en fait subdivisée en salles de classe. Ainsi, vos 512 élèves de terminale sont en fait divisés en 16 groupes de 32. De plus, aucune de ces écoles ne dispose réellement des ressources nécessaires : chaque classe ne possède que seize calculatrices. Par conséquent, à tout moment, seule la moitié de chaque classe peut passer votre test de mathématiques.

Le nombre de seniors, 512, représente le nombre de threads par bloc demandé lors du lancement d'un noyau CUDA. Le matériel d'implémentation peut diviser ce nombre en 16 blocs séquentiels de 32 threads pour traiter le nombre total de threads demandés, soit 512. Le chiffre 32 correspond à la taille de la chaîne, mais il peut varier selon les générations de matériel.

Je pourrais continuer à énumérer des règles stupides comme le fait que seules huit classes d'une même école peuvent passer le test en même temps parce qu'elles n'ont que huit enseignants. Vous ne pouvez pas échantillonner plus de 30 écoles simultanément parce que vous n'avez que 30 surveillants...

Je reviens à votre question :

Pour filer la métaphore, votre programme veut calculer les résultats le plus rapidement possible (vous voulez collecter des tests de mathématiques). Vous créez un noyau avec un certain nombre de blocs (écoles), chacun ayant un certain nombre de threads (élèves). Le nombre de blocs en cours d'exécution est limité (la collecte des réponses à l'enquête nécessite un surveillant par école). Dans CUDA, les blocs de threads s'exécutent sur un multiprocesseur en continu (SM). La variable : CL_DEVICE_MAX_COMPUTE_UNITS indique le nombre de SM, 30 une carte spécifique a. Cela varie considérablement en fonction du matériel -- consultez le tableau dans l'annexe A de la brochure Guide des meilleures pratiques CUDA C . Notez que chaque SM ne peut exécuter que huit blocs simultanément, quelle que soit la capacité de calcul (1.X ou 2.X).

Les blocs de filetage ont des dimensions maximales : CL_DEVICE_MAX_WORK_ITEM_SIZES . Pensez à la disposition de vos fils dans une grille ; vous ne pouvez pas avoir une ligne avec plus de 512 fils. Vous ne pouvez pas avoir une colonne avec plus de 512 fils. Et vous ne pouvez pas empiler plus de 64 fils élevés. Ensuite, il y a un maximum : CL_DEVICE_MAX_WORK_GROUP_SIZE le nombre de fils, 512 qui peuvent être regroupés en un bloc. Les dimensions de vos blocs de fils pourraient donc être les suivantes

512 x 1 x 1

1 x 512 x 1

4 x 2 x 64

64 x 8 x 1

etc...

Notez qu'à partir de Compute Capability 2.X, vos blocs peuvent avoir un maximum de 1024 threads. Enfin, la variable CL_NV_DEVICE_WARP_SIZE spécifie la taille de la chaîne, 32 (nombre d'élèves par classe). Dans les dispositifs Compute Capability 1.X, les transferts de mémoire et l'envoi d'instructions ont lieu au niveau de l'unité de traitement. Demi-flèche granularité (vous ne disposez que de 16 calculatrices par classe). Dans Compute Capability 2.0, les transferts de mémoire sont regroupés par Distorsion soit 32 opérations simultanées, mais l'envoi d'instructions n'est toujours groupé que par Demi-flèche . Pour la capacité de calcul 2.1, les deux transferts de mémoire et l'envoi d'instructions se fait par Distorsion 32 fils. Ces éléments peuvent changer et changeront dans le futur matériel.

Alors, ma parole ! Venons-en au fait :

En résumé :

J'ai décrit les nuances de la disposition de la chaîne et du fil et d'autres choses de ce genre, mais voici quelques points à garder à l'esprit. Tout d'abord, votre accès à la mémoire doit être "groupable" en ensembles de 16 ou 32. La dimension X de vos blocs doit donc être un multiple de 32. Deuxièmement, et surtout pour tirer le meilleur parti d'un gpu spécifique, il faut en maximiser l'occupation. N'ayez pas 5 blocs de 512 threads. Il ne faut pas non plus avoir 1 000 blocs de 10 threads. Je voudrais fortement recommandent de consulter le site Feuille de calcul basée sur Excel (travaux en OpenOffice aussi ?? Je pense ??) qui vous dira quelle sera l'occupation du GPU pour un appel spécifique du noyau (thread layout et les exigences en matière de mémoire partagée). J'espère que ces explications vous aideront !

2 votes

Très belle réponse et métaphore. Je voudrais juste ajouter qu'AMD a une notion similaire appelée Wavefront, et qu'il y a actuellement 64 threads/wavefront.

0 votes

Huh. Je ne le savais pas. Je n'ai pas passé beaucoup de temps à regarder les offres d'AMD. Avez-vous une idée si cela va changer radicalement avec les offres Fusion ?

0 votes

Les futurs composants de fusion sont tous basés sur l'architecture Evergreen, de sorte que wavefront devrait rester à 64 threads : highperformancegraphics.org/media/Hot3D/HPG2010_Hot3D_AMD.pdf

8voto

ArchaeaSoftware Points 2491

La "réponse directe" donnée ci-dessus est tout sauf directe. La taille de la chaîne est de 32 threads ; c'est l'unité à laquelle les multiprocesseurs de flux exécutent les instructions. Les SM ne sont pas en mesure d'exécuter des instructions à une granularité plus fine que 32.

Étant donné qu'une grande partie du code existant repose sur une taille de chaîne de 32 (y compris dans l'échantillon de code de réduction de NVIDIA), NVIDIA ne sera pas en mesure de modifier la taille de chaîne sans encourir un énorme problème de compatibilité. Je m'attends donc à ce qu'elle reste à 32 dans un avenir prévisible, et s'ils décident de la modifier d'une manière ou d'une autre, ils le feront en tant qu'opt-in. (c'est-à-dire que vous devrez demander la nouvelle taille de chaîne).

3voto

Matias Valdenegro Points 16473

La taille de la chaîne est le nombre de threads qu'un multiprocesseur exécute simultanément. Un multiprocesseur NVIDIA peut exécuter plusieurs threads du même bloc en même temps, en utilisant le multithreading matériel.

Il est important de tenir compte de la taille de la chaîne, car tous les accès à la mémoire sont regroupés en multiples de la taille de la chaîne (32 octets, 64 octets, 128 octets), ce qui améliore les performances.

En Guide des meilleures pratiques CUDA C contient toutes les informations techniques sur ce type d'optimisations.

2voto

Zaccur Points 63

La réponse directe est brève : Chez Nvidia, les BLOCs composés de THREADs sont définis par le programmeur, et WARP est de 32 (consiste en 32 threads), ce qui est l'unité minimale exécutée par l'unité de calcul en même temps. Chez AMD, le WARP est appelé WAVEFRONT ("vague").

Dans OpenCL, les WORKGROUPs signifient BLOCKs dans CUDA, et les WORKITEMs signifient THREADs dans CUDA.

0voto

vitrums Points 316

Je n'ai pas pu trouver de meilleure explication du warp qu'en lisant l'exemple vivant des optimisations, qui s'appuient sur le concept de warp. En quelques mots, le warp vient de SIMD paradigme. Quoi qu'il en soit, le réduction a clarifié cette question pour moi.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X