Как я могу указать минимальную вычислительную мощность компилятору mexcuda для компиляции функции mex?

avatar
Floris
10 октября 2018 в 13:10
260
1
1

У меня есть проект CUDA в файле .cu, который я хотел бы скомпилировать в файл .mex, используя mexcuda. Поскольку в моем коде используется 64-разрядная атомарная операция с плавающей запятой atomicAdd(double *, double), которая предназначена только для устройств GPU с вычислительной мощностью 6.0 или выше, мне нужно указать это как флаг при компиляции.

В моей стандартной среде IDE это работает нормально, но при компиляции с mexcuda это работает не так, как хотелось бы. В этой публикации на MathWorks было предложено использовать следующую команду (отредактировано из комментария Джосса Найта):

mexcuda('-v', 'mexGPUExample.cu', 'NVCCFLAGS=-gencode=arch=compute_60,code=sm_60')

, но когда я использую эту команду в своем файле, опция подробного вывода последней выводит следующую строку:

Building with 'NVIDIA CUDA Compiler'.
nvcc -c --compiler-options=/Zp8,/GR,/W3,/EHs,/nologo,/MD - 
gencode=arch=compute_30,code=sm_30 -gencode=arch=compute_50,code=sm_50 - 
gencode=arch=compute_60,code=sm_60 - 
gencode=arch=compute_70,code=\"sm_70,compute_70\"

(и так далее), что сигнализирует мне, что указанный флаг не был передан в nvcc должным образом. И действительно, компиляция не выполняется со следующей ошибкой:

C:/path/mexGPUExample.cu(35): error: no instance of overloaded function "atomicAdd" matches 
the argument list. Argument types are: (double *, double)

Единственный другой пост по этой теме, который я смог найти, был этот пост о SO, но ему почти три года, и мне показалось, что он больше похож на обходной путь, который я не понимаю даже после некоторого исследования, иначе я бы попробовал это - а не верное решение проблемы.

Есть ли параметр, который я пропустил, или это просто невозможно сделать без обходного пути?

Источник
Ander Biguri
10 октября 2018 в 15:04
1

Связанный пост предназначен только для mex, а не для mexcuda. Кроме того, поскольку по умолчанию выполняется компиляция для всех архитектур, передать этот флаг не должно быть проблемой. Ошибка вызвана чем-то другим, а не отсутствием флагов.

Ander Biguri
10 октября 2018 в 15:13
0

Можешь показать код? Ваша ошибка может быть вызвана неверным кодом

Robert Crovella
10 октября 2018 в 16:00
1

@AnderBiguri, вы получите эту ошибку, если скомпилируете с compute_30 и попытаетесь использовать double atomicAdd. Если вы используете в коде double atomicAdd, компилировать для всех архитектур - это не нормально. И это не значит, что это плохой код. Это означает, что вы не должны компилировать для compute_30, и OP спрашивает, как это сделать.

Ander Biguri
10 октября 2018 в 18:37
0

@RobertCrovella ну, это мог быть плохой код, но вы правы. Возможно, я просто не знаю достаточно, но можно предположить, что компиляция для всех архитектур означает, что генерируется код, который работает во всех архитектурах. Не больше ограничений, а меньше. Мое единственное предложение OP - использовать версию компиляции mex + xml, а не mexcuda. По моему опыту, с этим последним намного сложнее настроить параметры.

Robert Crovella
10 октября 2018 в 18:45
1

в целом ваша интуиция верна. Но если вы используете определенную функцию, которая недоступна в более низкой архитектуре, вы не можете использовать эту архитектуру. Например, перемешивание деформации - это функция cc3.0. Вы не можете скомпилировать встроенные функции warp shuffle для цели cc2.0. Вы получите ошибку компиляции.

Robert Crovella
10 октября 2018 в 18:45
2

Аналогичным образом double atomicAdd - это функция, для которой требуется cc6.0 или выше. Вы не можете скомпилировать его для архитектуры cc5.0 или ниже. если вы попытаетесь это сделать, даже если вы укажете несколько архитектур, вы получите ошибку компиляции. Следовательно, эти более низкие архитектуры должны быть удалены, что является сутью этого вопроса, поскольку он применяется к инструментальной цепочке mexcuda.

Floris
11 октября 2018 в 08:15
0

Спасибо за комментарии, господа. Мне удалось найти обходной путь, изменив файл xml в папке MatLab, который я опубликую в качестве ответа для других. Это не изящно, но, по крайней мере, у меня работает. Я также рассмотрю предложение mex + xml и отредактирую его в своем ответе, если найду что-нибудь, что работает. Я также посмотрю, смогу ли я уведомить кого-нибудь из MathWorks об этой «проблеме».

Floris
11 октября 2018 в 08:33
0

@Ander, что касается вашего третьего комментария: вы правы в w.r.t. компиляция для всех архитектур. Компиляция для всех архитектур приведет к увеличению размера файла для файла функции .mex, потому что он будет содержать отдельный код для каждого и использовать соответствующий код в зависимости от архитектуры, из которой он был вызван, что обеспечивает лучшую переносимость. Моя скомпилированная функция не будет работать ни на одном графическом процессоре с более низкой вычислительной мощностью (по крайней мере, не должна ..)

Ander Biguri
11 октября 2018 в 08:36
0

@RobertCrovella, это, безусловно, справедливое поведение. Спасибо, что научили нас (возможно, только меня), как обычно :)

Ответы (1)

avatar
Floris
11 октября 2018 в 08:30
1

Я смог обойти эту проблему после некоторого возни со стандартными xml -файлами в папке MatLab. Следующие шаги позволили мне скомпилировать с использованием -mexcuda:

-1) Перейдите в папку C:\Program Files\MATLAB\-version-\toolbox\distcomp\gpu\extern\src\mex\win64, которая содержит xml -файлы для разных версий msvcpp;

-2) Сделайте резервную копию файла, соответствующего используемой вами версии. В моем случае я сделал копию файла nvcc_msvcpp2017 и назвал его nvcc_msvcpp2017_old, чтобы всегда иметь оригинал.

-3) Откройте nvcc_msvcppYEAR с помощью блокнота и перейдите к следующему блоку строк:

COMPILER="nvcc"
COMPFLAGS="--compiler-options=/Zp8,/GR,/W3,/EHs,/nologo,/MD $ARCHFLAGS"
ARCHFLAGS="-gencode=arch=compute_30,code=sm_30 -gencode=arch=compute_50,code=sm_50 -gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_70,code=\"sm_70,compute_70\" $NVCC_FLAGS"
COMPDEFINES="--compiler-options=/D_CRT_SECURE_NO_DEPRECATE,/D_SCL_SECURE_NO_DEPRECATE,/D_SECURE_SCL=0,$MATLABMEX"
MATLABMEX="/DMATLAB_MEX_FILE"
OPTIMFLAGS="--compiler-options=/O2,/Oy-,/DNDEBUG"
INCLUDE="-I"$MATLABROOT\extern\include" -I"$MATLABROOT\simulink\include""
DEBUGFLAGS="--compiler-options=/Z7"

-4) Удалите архитектуры, которые не позволяют компилировать ваш код, т.е. все флаги архитектуры ниже 60 в моем случае:

ARCHFLAGS="-gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_70,code=\"sm_70,compute_70\" $NVCC_FLAGS"

-5) После этого я смог скомпилировать с использованием mexcuda. Вам не нужно указывать какие-либо флаги архитектуры в вызове mexcuda.

-6) (необязательно) Я полагаю, вы хотите отменить это изменение после того, как закончите работу над проектом, который требовал от вас этого изменения, если вы хотите обеспечить максимальную переносимость кода, который вы скомпилируете после этого.

Примечание : для внесения этих изменений вам потребуются права администратора.

Ander Biguri
11 октября 2018 в 08:38
0

Из любопытства: при использовании mex вместо mexcuda способ, которым вы делаете это, чтобы избежать завинчивания файлов MATLAB, - это скопировать и вставить файл xml и поместить его в текущую папку. Таким образом, когда вызывается mex, вместо поиска своего собственного файла xml в пути MATLAB он захватывает файл в текущей рабочей папке. Можете ли вы сделать это с помощью mexcuda?

Floris
11 октября 2018 в 08:53
0

Вы каким-либо образом изменяете свой звонок на mex? Без него, если я помещу исходный файл xml в свою текущую рабочую папку, он по-прежнему будет использовать файл в папке на шаге 1) моего ответа выше.

Ander Biguri
11 октября 2018 в 08:54
0

Да, я изменил файл xml, и, конечно, mex выбирает текущую папку перед той, которая указана в пути MATLAB. mexcuda может работать иначе.