CUDA: как использовать -arch и -code и SM против COMPUTE
Я до сих пор не уверен, как правильно указать архитектуры для генерации кода при сборке с nvcc. Я знаю, что в моем двоичном файле есть машинный код, а также код PTX, и этим можно управлять с помощью переключателей контроллера. -code
а также -arch
(или сочетание обоих с использованием -gencode
).
Теперь, в соответствии с этим, помимо двух флагов компилятора, есть также два способа задания архитектур: sm_XX
а также compute_XX
, где compute_XX
относится к виртуальному и sm_XX
к настоящей архитектуре. Флаг -arch
принимает только идентификаторы для виртуальных архитектур (таких как compute_XX
) тогда как -code
Флаг принимает как идентификаторы для реальной и виртуальной архитектуры.
В документации говорится, что -arch
определяет виртуальные архитектуры, для которых скомпилированы входные файлы. Однако этот код PTX автоматически не компилируется в машинный код, а скорее является "этапом предварительной обработки".
Сейчас, -code
Предполагается указать, для каких архитектур код PTX собирается и оптимизируется.
Однако не ясно, какой PTX или двоичный код будет встроен в двоичный файл. Если я укажу например -arch=compute_30 -code=sm_52
Означает ли это, что мой код будет сначала скомпилирован для PTX уровня 3.0, из которого впоследствии будет создан машинный код для уровня 5.2? А что будет встроено?
Если я просто укажу -code=sm_52
что будет потом? Будет внедрен только машинный код для V5.2, созданный из кода PTX V5.2? И какая разница -code=compute_52
?
1 ответ
Некоторые связанные вопросы / ответы здесь и здесь.
Я до сих пор не уверен, как правильно указать архитектуры для генерации кода при сборке с nvcc.
Полное описание несколько сложное, но предполагается, что оно будет относительно простым, легко запоминающимся каноническим использованием. Компилируйте для архитектуры (как виртуальной, так и реальной), представляющей графические процессоры, на которые вы хотите ориентироваться. Довольно простая форма:
-gencode arch=compute_XX,code=sm_XX
где XX - это двухзначная вычислительная возможность для GPU, на который вы хотите ориентироваться. Если вы хотите использовать несколько графических процессоров, просто повторите всю последовательность для каждой цели XX. Это примерно тот подход, который используется с примерами проектов кода CUDA. (Если вы хотите включить PTX в свой исполняемый файл, добавьте дополнительный -gencode
с code
опция, указывающая ту же виртуальную архитектуру PTX, что и arch
опция).
Другая довольно простая форма, предназначенная только для одного графического процессора, заключается в следующем:
-arch=sm_XX
с таким же описанием для XX. Эта форма будет включать в себя как SASS, так и PTX для указанной архитектуры.
Теперь, в соответствии с этим, помимо двух флагов компилятора, есть также два способа указания архитектур: sm_XX и compute_XX, где compute_XX относится к виртуальной, а sm_XX к реальной архитектуре. Флаг -arch принимает только идентификаторы для виртуальных архитектур (таких как compute_XX), тогда как флаг -code принимает оба идентификатора для реальной и для виртуальных архитектур.
Это в основном правильно, когда arch
а также code
используются в качестве вспомогательных переключателей в -gencode
Переключатель или, если оба используются вместе, автономно, как вы описываете. Но, например, когда -arch
используется сам по себе (без -code
), он представляет другой вид "сокращенной" нотации, и в этом случае вы можете передать реальную архитектуру, например -arch=sm_52
Однако не ясно, какой PTX или двоичный код будет встроен в двоичный файл. Например, если я укажу -arch=compute_30 -code=sm_52, означает ли это, что мой код будет сначала скомпилирован в PTX уровня возможностей 3.0, из которого впоследствии будет создан машинный код для уровня функций 5.2? А что будет встроено?
Точное определение того, что внедряется, варьируется в зависимости от формы использования. Но для этого примера:
-gencode arch=compute_30,code=sm_52
или для эквивалентного случая вы определяете:
-arch=compute_30 -code=sm_52
тогда да, это означает, что:
- Временный код PTX будет сгенерирован из вашего исходного кода, и он будет использовать cc3.0 PTX.
- Из этого PTX
ptxas
Инструмент сгенерирует код SASS, соответствующий cc5.2. - Код SASS будет встроен в ваш исполняемый файл.
- Код PTX будет отброшен.
(Я не уверен, почему вы бы указали такую комбинацию, но это законно.)
Если я просто укажу -code = sm_52, что будет потом? Будет внедрен только машинный код для V5.2, созданный из кода PTX V5.2? И в чем будет разница с -code=compute_52?
-code=sm_52
сгенерирует код SASS cc5.2 из промежуточного кода PTX. Код SASS будет встроен, PTX будет сброшен. Обратите внимание, что указание этой опции само по себе в этой форме, без -arch
вариант, будет незаконным. (1)
-code=compute_52
сгенерирует код PTX cc5.x (только) и вставит этот PTX в исполняемый файл / двоичный файл. Обратите внимание, что указание этой опции само по себе в этой форме, без -arch
вариант, будет незаконным. (1)
cuobjdump
Инструмент может быть использован, чтобы определить, какие именно компоненты находятся в данном двоичном файле.
(1) Когда нет -gencode
переключатель используется, и нет -arch
переключатель используется, nvcc
предполагает дефолт -arch=sm_20
добавлен к вашей команде компиляции (это для CUDA 7.5, по умолчанию -arch
настройка может варьироваться в зависимости от версии CUDA). sm_20
является реальной архитектурой, и не разрешено указывать настоящую архитектуру на -arch
вариант, когда -code
опция также поставляется.