web-dev-qa-db-fra.com

CUDA: Comment utiliser -Arch et -code et SM vs COMPUTE

Je ne sais toujours pas comment spécifier correctement les architectures pour la génération de code lors de la construction avec nvcc. Je suis conscient qu'il y a du code machine ainsi que du code PTX intégrés dans mon binaire et que cela peut être contrôlé via les commutateurs du contrôleur -code et -Arch (ou une combinaison des deux en utilisant -gencode).

Maintenant, selon this à part les deux drapeaux du compilateur, il y a aussi deux façons de spécifier les architectures: sm_XX et compute_XX, où compute_XX fait référence à un virtuel et sm_XX à une véritable architecture. Le drapeau -Arch ne prend que des identifiants pour les architectures virtuelles (telles que compute_XX) tandis que le -code flag prend les deux identifiants pour les architectures réelles et virtuelles.

La documentation indique que -Arch spécifie les architectures virtuelles pour lesquelles les fichiers d'entrée sont compilés. Cependant, ce code PTX n'est pas automatiquement compilé en code machine, mais il s'agit plutôt d'une "étape de prétraitement".

À présent, -code est censé spécifier les architectures pour lesquelles le code PTX est assemblé et optimisé.

Cependant, il n'est pas clair quel code PTX ou binaire sera incorporé dans le binaire. Si je spécifie par exemple -Arch=compute_30 -code=sm_52, cela signifie-t-il que mon code sera d'abord compilé au niveau de fonctionnalité 3.0 PTX à partir duquel sera ensuite créé le code machine pour le niveau de fonctionnalité 5.2? Et qu'est-ce qui sera intégré?

Si je spécifie simplement -code=sm_52 que se passera-t-il alors? Seul le code machine pour V5.2 sera incorporé qui a été créé à partir du code PTX V5.2? Et quelle serait la différence avec -code=compute_52?

27
bweber

Certaines questions/réponses connexes sont ici et ici .

Je ne sais toujours pas comment spécifier correctement les architectures pour la génération de code lors de la construction avec nvcc.

Une description complète est quelque peu compliquée, mais il est censé être des usages canoniques relativement simples et faciles à retenir. Compilez pour l'architecture (virtuelle et réelle), qui représente les GPU que vous souhaitez cibler. Un formulaire assez simple est:

-gencode Arch=compute_XX,code=sm_XX

où XX est la capacité de calcul à deux chiffres pour le GPU que vous souhaitez cibler. Si vous souhaitez cibler plusieurs GPU, répétez simplement la séquence entière pour chaque XX cible. Il s'agit approximativement de l'approche adoptée avec les exemples de projets de code CUDA. (Si vous souhaitez inclure PTX dans votre exécutable, ajoutez un -gencode Supplémentaire avec l'option code spécifiant la même architecture virtuelle PTX que l'option Arch).

Une autre forme assez simple, lorsque vous ciblez un seul GPU, consiste simplement à utiliser:

-Arch=sm_XX 

avec la même description pour XX. Ce formulaire comprendra à la fois SASS et PTX pour l'architecture spécifiée.

Désormais, en dehors de ces deux drapeaux du compilateur, il existe également deux façons de spécifier les architectures: sm_XX et compute_XX, où compute_XX fait référence à une architecture virtuelle et sm_XX à une architecture réelle. L'indicateur -Arch ne prend que des identifiants pour les architectures virtuelles (comme compute_XX) tandis que l'indicateur -code prend les deux, des identifiants pour les architectures réelles et virtuelles.

Ceci est fondamentalement correct lorsque Arch et code sont utilisés comme sous-commutateurs dans le commutateur -gencode, Ou si les deux sont utilisés ensemble , autonome comme vous le décrivez. Mais, par exemple, lorsque -Arch Est utilisé seul (sans -code), Il représente un autre type de notation "abrégée", et dans ce cas, vous pouvez passer une architecture réelle, par exemple -Arch=sm_52

Cependant, il n'est pas clair quel code PTX ou binaire sera incorporé dans le binaire. Si je spécifie par exemple -Arch = compute_30 -code = sm_52, cela signifie-t-il que mon code sera d'abord compilé au niveau de fonctionnalité PTX 3.0 à partir duquel sera ensuite créé le code machine pour le niveau de fonctionnalité 5.2? Et qu'est-ce qui sera intégré?

La définition exacte de ce qui est intégré varie en fonction de la forme d'utilisation. Mais pour cet exemple:

-gencode Arch=compute_30,code=sm_52

ou pour le cas équivalent que vous identifiez:

-Arch=compute_30 -code=sm_52

alors oui, cela signifie que:

  1. Un code PTX temporaire sera généré à partir de votre code source et il utilisera cc3.0 PTX.
  2. À partir de ce PTX, l'outil ptxas générera du code SASS conforme à cc5.2.
  3. Le code SASS sera intégré à votre exécutable.
  4. Le code PTX sera supprimé.

(Je ne sais pas pourquoi vous spécifieriez un tel combo, mais c'est légal.)

Si je spécifie simplement -code = sm_52, que se passera-t-il alors? Seul le code machine pour V5.2 sera incorporé qui a été créé à partir du code PTX V5.2? Et quelle serait la différence avec -code = compute_52?

-code=sm_52 Générera du code cc5.2 SASS à partir d'un code PTX intermédiaire. Le code SASS sera intégré, le PTX sera rejeté. Notez que la spécification de cette option seule dans ce formulaire, sans option -Arch, Serait illégale. (1)

-code=compute_52 Générera du code cc5.x PTX (uniquement) et incorporera ce PTX dans l'exécutable/binaire. Notez que la spécification de cette option seule dans ce formulaire, sans option -Arch, Serait illégale. (1)

Le cuobjdumpoutil peut être utilisé pour identifier quels composants sont exactement dans un binaire donné.

(1) Lorsqu'aucun commutateur -gencode N'est utilisé et qu'aucun commutateur -Arch N'est utilisé, nvcc suppose qu'un -Arch=sm_20 Par défaut est ajouté à votre commande de compilation (ce concerne CUDA 7.5, le paramètre par défaut -Arch peut varier selon la version de CUDA). sm_20 Est une architecture réelle , et il n'est pas légal de spécifier une réelle architecture sur l'option -Arch lorsqu'une option -code est également fournie.

27
Robert Crovella