Quelle est la relation entre la taille maximale du groupe de travail et la taille de la chaîne? Supposons que mon appareil dispose de 240 processeurs de streaming CUDA (SP) et 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 a huit SP par multiprocesseur en streaming (c'est-à-dire une unité de calcul). Maintenant, comment la taille de chaîne = 32 est-elle liée à ces nombres?
Réponse directe: La taille de 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 la distribution des instructions .
Lecture suggérée:
Comme @Matias l'a mentionné, j'irais lire le CUDA C Best Practices Guide (vous devrez faire défiler vers le bas où il est répertorié). Il peut être utile pour vous de regarder le tableau de l'annexe G.1 à la page 164.
Explication:
CUDA est un langage qui assure le parallélisme à deux niveaux. Vous avez des fils et vous avez des blocs de fils. Ceci est plus é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 vous dit pas, c'est que les choses se passent en réalité à quatre niveaux, pas à 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 aider à expliquer ce qui se passe réellement:
Brève métaphore:
Imaginez que vous êtes un éducateur/chercheur/politicien qui s'intéresse à la capacité mathématique actuelle des personnes âgées du secondaire. Votre plan est de donner un test à 10 240 étudiants, mais vous ne pouvez pas simplement les mettre tous dans un stade de football ou quelque chose et leur donner le test. Il est plus facile de subdiviser (paralléliser) votre collecte de données - vous allez donc dans 20 lycées différents et demandez à 512 de leurs aînés de passer chacun le test de mathématiques.
Vous collectez vos données et c'est tout ce dont vous vous souciez. Ce que vous ne saviez pas (et que vous ne vous souciez pas vraiment), c'est que chaque école est en fait subdivisée en classes. Ainsi, vos 512 personnes âgées sont en fait divisées en 16 groupes de 32. Et en outre, aucune de ces écoles n'a vraiment les ressources nécessaires - chaque classe n'a que seize calculatrices. Par conséquent, à tout moment, seule la moitié de chaque classe peut passer votre test de mathématiques.
Je pourrais continuer à étirer des règles idiotes, comme seulement huit salles de classe dans une même école peuvent passer le test à la fois car elles n'ont que huit enseignants. Vous ne pouvez pas échantillonner plus de 30 écoles simultanément car vous n'avez que 30 surveillants ...
Retour à votre question:
En utilisant la métaphore, votre programme veut calculer les résultats aussi rapidement que possible (vous voulez collecter des tests mathématiques). Vous émettez un noyau avec un certain nombre de blocs (écoles) dont chacun a un certain nombre de threads (étudiants). Vous ne pouvez exécuter qu'un nombre limité de blocs à la fois (la collecte des réponses à votre enquête nécessite un surveillant par école). Dans CUDA, les blocs de threads s'exécutent sur un multiprocesseur de streaming (SM). La variable: CL_DEVICE_MAX_COMPUTE_UNITS
vous indique combien de SM, 30 , une carte spécifique possède. Cela varie considérablement en fonction du matériel - consultez le tableau de l'annexe A du 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 à disposer vos fils dans une grille; vous ne pouvez pas avoir une ligne avec plus de 512 threads. Vous ne pouvez pas avoir une colonne avec plus de 512 threads. Et vous ne pouvez pas empiler plus de 64 threads de haut. Ensuite, il y a un maximum: CL_DEVICE_MAX_WORK_GROUP_SIZE
nombre de threads, 512 , qui peuvent être regroupés dans un bloc. Ainsi, les dimensions de vos blocs de filetage pourraient être:
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 au plus 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 appareils Compute Capability 1.X, les transferts de mémoire et la répartition des instructions se produisent à la granularité Half-Warp (vous ne disposez que de 16 calculatrices par classe). Dans Compute Capability 2.0, les transferts de mémoire sont regroupés par Warp , donc 32 récupérations simultanément, mais la répartition des instructions n'est toujours groupée que par Demi-chaîne . Pour Compute Capability 2.1, les deux transferts de mémoire et envoi des instructions se produisent par Warp , 32 threads. Ces choses peuvent et vont changer 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 chaîne/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" par ensembles de 16 ou 32. Donc, gardez la dimension X de vos blocs un multiple de 32. Deuxièmement, et le plus important pour tirer le meilleur parti d'un processeur spécifique, vous devez maximiser l'occupation. Ne pas avoir 5 blocs de 512 threads. Et ne pas avoir 1000 blocs de 10 threads. Je recommanderais fortement de vérifier la feuille de calcul basée sur Excel (fonctionne dans OpenOffice aussi ??) Je pense ??) qui vous dira quelle sera l'occupation du GPU pour un appel spécifique au noyau (disposition des threads et exigences de mémoire partagée). J'espère que cette explication aide!
La taille de chaîne est le nombre de threads qu'un multiprocesseur exécute simultanément. Un multiprocesseur NVIDIA peut exécuter plusieurs threads à partir du même bloc en même temps, en utilisant le multithreading matériel.
Il est important de prendre en compte la taille de chaîne, car tous les accès à la mémoire sont fusionnés en multiples de la taille de chaîne (32 octets, 64 octets, 128 octets), ce qui améliore les performances.
Le CUDA C Best Practices Guide contient toutes les informations techniques sur ce type d'optimisations.
La réponse directe est brève: dans Nvidia, les BLOCS composés de THREADs sont définis par le programmeur, et WARP est de 32 (composé de 32 threads), qui est l'unité minimale exécutée simultanément par l'unité de calcul. Dans AMD, WARP est appelé WAVEFRONT ("wave").
Dans OpenCL, WORKGROUPs signifie BLOCS dans CUDA, et WORKITEMs signifie THREADs dans CUDA.