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
?
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:
ptxas
générera du code SASS conforme à cc5.2.(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 cuobjdump
outil 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.