我正在使用CUDA并尝试使用函数指针将CUDA函数传递给稍后在其设备内核中使用此函数的库,类似于CUDA函数指针示例。
代码的重要部分是:
/** Type definition for the execution function in #qsched_run. */
typedef void (*qsched_funtype)( int , void * );
__device__ void gpuTest(int type , void *data)
{
....
}
__device__ qsched_funtype function = gpuTest;
void main(...)
{
//Various initialization setup.
if( cudaMemcpyFromSymbol( &func , function , sizeof(qsched_funtype) ) != cudaSuccess)
error("Failed to copy function pointer from device");
qsched_run_CUDA( &s , func );
}
qsched_run_CUDA函数是一个库函数,它执行一些初始化,将函数指针复制到设备(它可以看到的变量),然后运行一个内核,在某些点使用该函数指针调用gpuTest函数。
代码编译正确,前提是我使用-G和以下nvcc调用:
nvcc -g -G -m64 -I../src ../src/.libs/libquicksched_cuda.a -L/home/aidan/cuda_6.0/lib -L/home/aidan/cuda_6.0/lib64 -lcudart -lcuda -DWITH_CUDA -gencode arch=compute_30,code=sm_30 -lgomp test_gpu_simple.cu -o out.out
,其中
../src/.libs/libquicksched_cuda.a
是包含qsched_run_CUDA函数的库。
当我从我的nvcc调用中删除-G标志然后突然全部中断,并且qsched_run_CUDA中运行的内核因 无效程序计数器 错误而崩溃,并且函数指针(包括在我自己的.cu文件中)设置为0x4。
据推测,我需要在http://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#using-separate-compilation-in-cuda中隐约解释使用CUDA中的单独编译(Cuda function pointer consistency) - 但是我不确定如何在使用库函数时这样做,既不是nvcc的指南也不是stackoverflow链接明确了如何做到这一点。
有没有人有这方面的经验?我试图简单地尝试使用nvlink来做到这一点,但是我没有做得很远(我把它传给了一个库似乎并不高兴。)
答案 0 :(得分:3)
是的,您需要使用单独的编译。我根据您到目前为止所展示的内容整理了一个简单的测试用例,并使用文档中的nvcc separate compilation library example。这是代码:
kernel_lib.cu:
#include <stdio.h>
#define cudaCheckErrors(msg) \
do { \
cudaError_t __err = cudaGetLastError(); \
if (__err != cudaSuccess) { \
fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \
msg, cudaGetErrorString(__err), \
__FILE__, __LINE__); \
fprintf(stderr, "*** FAILED - ABORTING\n"); \
exit(1); \
} \
} while (0)
/** Type definition for the execution function in #qsched_run. */
typedef void (*qsched_funtype)( int , void * );
__global__ void mykernel(int type, void *data, void *func){
((qsched_funtype)func)(type, data);
}
int qsched_run_CUDA(int val, void *d_data, void *func)
{
mykernel<<<1,1>>>(val, d_data, func);
cudaDeviceSynchronize();
cudaCheckErrors("kernel fail");
return 0;
}
main.cu:
#include <stdio.h>
#define DATA_VAL 5
int qsched_run_CUDA(int, void*, void*);
#define cudaCheckErrors(msg) \
do { \
cudaError_t __err = cudaGetLastError(); \
if (__err != cudaSuccess) { \
fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \
msg, cudaGetErrorString(__err), \
__FILE__, __LINE__); \
fprintf(stderr, "*** FAILED - ABORTING\n"); \
exit(1); \
} \
} while (0)
/** Type definition for the execution function in #qsched_run. */
typedef void (*qsched_funtype)( int , void * );
__device__ void gpuTest(int type , void *data)
{
((int *)data)[0] = type;
}
__device__ qsched_funtype function = gpuTest;
int main()
{
void *func;
cudaMemcpyFromSymbol( &func , function , sizeof(qsched_funtype));
cudaCheckErrors("Failed to copy function pointer from device");
int h_data = 0;
int *d_data;
cudaMalloc((void **)&d_data, sizeof(int));
cudaCheckErrors("cudaMalloc fail");
cudaMemset(d_data, 0, sizeof(int));
cudaCheckErrors("cudaMemset fail");
int return_val = qsched_run_CUDA(DATA_VAL, (void *)d_data, func);
if (return_val != 0) printf("return code error\n");
cudaMemcpy(&h_data, d_data, sizeof(int), cudaMemcpyDeviceToHost);
cudaCheckErrors("cudaMemcpy fail");
if (h_data != DATA_VAL) {printf("Fail! %d\n", h_data); return 1;}
printf("Success!\n");
return 0;
}
编译命令和结果:
$ nvcc -arch=sm_20 -dc kernel_lib.cu
$ nvcc -lib kernel_lib.o -o test.a
$ nvcc -arch=sm_20 -dc main.cu
$ nvcc -arch=sm_20 main.o test.a -o test
$ ./test
Success!
$
我使用CUDA 5.0进行此测试。