Modèle CUDA – quelle est la taille de la chaîne?

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 continu (c’est-à-dire, unité de calcul). Maintenant, comment la taille de la chaîne = 32 est-elle liée à ces chiffres?

Réponse directe: La taille de Warp est le nombre de threads d’un warp, qui est une sous-division utilisée dans l’implémentation matérielle pour fusionner l’access à la mémoire et la répartition des instructions.

Lecture suggérée:

Comme @Matias l’a mentionné, j’irais lire le Guide des meilleures pratiques de CUDA C (vous devrez faire défiler vers le bas où il est répertorié). Il pourrait vous être utile de regarder le tableau de l’annexe G.1 à la page 164.

Explication:

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

Ce que CUDA ne vous dit pas, c’est que les choses se passent à 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 expliquer ce qui se passe réellement:

Brève métaphore:

Imaginez que vous êtes un enseignant / chercheur / politicien qui s’intéresse à la capacité mathématique actuelle des aînés du secondaire. Votre plan est de faire passer un test à 10 240 élèves, mais vous ne pouvez pas simplement les mettre 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 allez donc à 20 écoles secondaires différentes et demandez à 512 personnes âgées de passer le test de mathématiques.

Vous collectez vos données et c’est tout ce qui vous intéresse. Ce que vous ne saviez pas (et qui ne vous intéressait pas vraiment ), c’est que chaque école est divisée en salles de classe. Donc, vos 512 aînés sont divisés en 16 groupes de 32. En outre, aucune de ces écoles ne dispose vraiment des ressources nécessaires – chaque salle de classe ne compte que seize calculasortingces. 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 stupides, car seules huit salles de classe dans une même école peuvent passer le test en même temps, car elles ne comptent que huit enseignants. Vous ne pouvez pas échantillonner plus de 30 écoles simultanément, car vous ne disposez que de 30 surveillants …

Retour à votre question:

En utilisant la métaphore, votre programme veut calculer les résultats aussi rapidement que possible (vous souhaitez collecter des tests mathématiques). Vous émettez un kernel avec un certain nombre de blocs (écoles) ayant chacun un certain nombre de threads (étudiants). Vous ne pouvez avoir qu’un si grand nombre de blocs en même temps (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 diffusion (SM). La variable: CL_DEVICE_MAX_COMPUTE_UNITS vous indique combien de SM, 30 , une carte spécifique a. Cela varie considérablement en fonction du matériel – consultez le tableau dans 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 threads ont des dimensions maximales: CL_DEVICE_MAX_WORK_ITEM_SIZES . Pensez à exposer vos discussions dans une grid; 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 emstackr 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. Les dimensions de vos blocs de fil peuvent donc ê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 contenir au maximum 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 Compute Capability Devices 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 calculasortingces par classe). Dans Compute Capability 2.0, les transferts de mémoire sont regroupés par Warp , donc 32 récupérations simultanées, mais la répartition des instructions n’est encore groupée que par Half-Warp . Pour Compute Capability 2.1, les transferts de mémoire et l’ envoi des instructions se font par Warp , 32 threads. Ces choses peuvent et vont changer dans le futur matériel.

Alors, ma parole! Allons au point:

En résumé:

J’ai décrit les nuances de la disposition de la chaîne / du fil et d’autres shtuff, mais voici quelques points à garder à l’esprit. Tout d’abord, votre access mémoire doit être “groupable” par 16 ou 32. Conservez donc la dimension X de vos blocs un multiple de 32. Deuxièmement, et le plus important pour tirer le maximum d’un GPU 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 recommande fortement de consulter le tableur basé sur Excel (fonctionne aussi dans OpenOffice, je pense?), Qui vous indiquera quelle sera l’occupation du GPU pour un appel de kernel spécifique (disposition du thread et mémoire partagée). J’espère que cette explication est utile!

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

Il est important de prendre en compte la taille de la chaîne, car tous les access 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.

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

La réponse directe est brève: en Nvidia, les BLOCS composés par THREAD sont définis par le programmeur et WARP 32 (composé de 32 threads), qui est l’unité minimale exécutée par l’unité de calcul en même temps. Dans AMD, WARP s’appelle WAVEFRONT (“wave”).

Dans OpenCL, les WORKGROUP signifient BLOCK dans CUDA, de plus, WORKITEM signifie THREAD dans CUDA.