Согласованность указателя функции Cuda

Недавно я пытался использовать указатель функции для динамического определения нескольких этапов обработки в моем приложении, работающем на sm_30.

Было бы сложно опубликовать код здесь, так как задействовано много разных файлов и функций, но в основном я начал с образца, который был включен в Cuda Toolkit 5.0.

Я выделяю буфер функции устройства, куда копирую указатель функции устройства, определенный так же, как в примере, благодаря cudaMemcpyfromsymbolAsync, используемому с типом копии DeviceToDevice.

Указатель моего устройства определяется следующим образом в .cu.h :

//device function pointer model
typedef void (*func)(structGpuArgument*);

//Declaring a function
__device__ void gpuFunc1(structGpuArgument* arg1);

в другом месте у меня есть .cu, который включает предыдущее объявление, содержащее следующий код:

//get the actual function pointer
__device__ func gpuFuncPtr = gpuFunc1;

//Buffer to store a list of function pointer
func* pFuncDevBuffer;
cudaMalloc(&pFuncDevBuffer,NB_FUNC*sizeof(func));

//copy the actual function pointer (symbol) to the list buffer 
cudaMemcpyFromSymbolAsync( pFuncDevBuffer+i ,gpuFuncPtr,sizeof(func),0,cudaMemcpyDeviceToDevice,stream)

//Launch the kernel that will use the functions
kernel_test<<<1,10,0,stream>>>(pFuncDevBuffer)
...

//defining the kernel that uses pointer buffer
__global__ void kernel_test(func* pFuncDevBuffer)
{
   printf("func address : %p\n",pFuncDevBuffer[0]);
   pFuncDevBuffer[0](NULL);
}

//defining the function pointed by the function pointer
__device__ void gpuFunc1(structGpuArgument* arg1)
{
     do_something;
}

На самом деле все работает нормально, пока глобальное ядро, принимающее в качестве аргумента буфер функции device, определено в том же файле, что и функция и ее указатель. Затем ядро ​​​​может распечатать адрес функции (0x4) и выполнить ее код без проблем. Я не использую отдельную компиляцию.

Когда в том же экземпляре программы второе ядро, определенное в другом месте, принимает в качестве аргумента тот же самый буфер указателя функции, оно может распечатать тот же самый адрес памяти для указателя функции (0x4), но если оно попытается выполнить его, оно не удается выдать недопустимую инструкцию по адресу 0x00000000 в cuda-memcheck. Любой другой вызов API cuda зависает после этого, мне нужно перезагрузить компьютер (сброс через cuda-smi не поддерживается на моем графическом процессоре).

Я хотел бы знать, существует ли известная проблема с использованием указателя функции таким образом, т.е. с использованием буфера указателя функции, определенного в другом файле, но с использованием одного и того же определения указателя функции.

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

спасибо за помощь


person Tobbey    schedule 07.05.2013    source источник
comment
Вы связываете код устройства в 2 отдельных файлах вместе. Вам нужно использовать компоновщик устройств.   -  person Robert Crovella    schedule 07.05.2013
comment
@RobertCrovella Спасибо за ваш ответ, но не могли бы вы быть более конкретным? Потому что на данный момент у меня нет ошибки связывания, и я использую CUDA.Cmake для сборки своего проекта, что скрывает от меня часть процесса компиляции/связывания. Насколько мне известно, в графическом процессоре nvidia нет памяти, ограниченной процессами, так почему же мое ядро ​​​​не может получить доступ и загрузить код с адреса, считанного из буфера (0x4)?   -  person Tobbey    schedule 07.05.2013
comment
После воспроизведения проблемы на простом примере кажется, что вы правы. В nsight я сгенерировал неудачную версию, скомпилированную в режиме всей программы, и успешную, ничего не перекодируя, кроме установки отдельной опции компиляции. Моя проблема в том, что, во-первых, я не понимаю документацию nvcc, что именно означают перемещаемый код устройства и разделяемая компиляция, и какое это имеет отношение к моей проблеме. С другой стороны, при попытке использовать отдельную компиляцию и перемещаемый код устройства на cuda.cmake я получаю множество ошибок привязки неопределенных ссылок.   -  person Tobbey    schedule 07.05.2013
comment
Извините, я был в самолете. Кажется, вы на пути к пониманию этого. Если у вас есть код устройства в двух файлах, которые должны вызывать или ссылаться друг на друга, вам необходимо использовать компоновщик устройств (который используется при выборе отдельной компиляции). Вы можете прочитать этот раздел руководства по nvcc на docs.nvidia.com. Извините, я не могу помочь с cmake.   -  person Robert Crovella    schedule 07.05.2013