问题
我正在尝试将int
数组复制到设备的常量内存中,但我不断收到以下错误:
[错误]在'main.cu'第386行''中的'无效参数'(11)
代码
开发了很多代码,所以我将简化我所拥有的代码。
我在main.cu文件的顶部声明了一个设备__constant__
变量,在任何函数之外。
__device__ __constant__ int* dic;
我还有一个主变量flatDic
,它在main()
内以下列方式进行了malloc:
int* flatDic = (int *)malloc(num_codewords*(bSizeY*bSizeX)*sizeof(int));
然后我尝试将flatDic
的内容复制到dic
这样做,同样在main()
中:
cudaMemcpyToSymbol(dic, flatDic, num_codewords*(bSizeY*bSizeX)*sizeof(int));
这个cudaMemcpyToSymbol()
称它为main.cu的第386行,它就是抛出上述错误的地方。
我尝试了什么
以下是我迄今为止尝试解决问题的方法:
我已经尝试了以下所有方法,总是返回相同的错误:
cudaMemcpyToSymbol(dic, &flatDic, num_codewords*(bSizeY*bSizeX)*sizeof(int));
cudaMemcpyToSymbol(dic, flatDic, num_codewords*(bSizeY*bSizeX)*sizeof(int));
cudaMemcpyToSymbol(dic, &flatDic, num_codewords*(bSizeY*bSizeX)*sizeof(int), 0, cudaMemcpyHostToDevice);
cudaMemcpyToSymbol(dic, flatDic, num_codewords*(bSizeY*bSizeX)*sizeof(int), 0, cudaMemcpyHostToDevice);
在调用cudaMalloc()
之前,我还尝试dic
cudaMemcpyToSymbol()
变量。 cudaMalloc()
不会引发任何错误,但cudaMemcpyToSymbol()
错误仍然存在。
cudaMalloc((void **) &dic, num_codewords*(bSizeY*bSizeX)*sizeof(int));
我还广泛搜索网络,文档,论坛,示例等,但都无济于事。
有人看到我的代码有什么问题吗?提前谢谢。
答案 0 :(得分:4)
cudaMemcpyToSymbol
复制到常量变量,这里您尝试将类型为int
的多个字节(已分配的ARRAY)复制到类型int *
的指针。这些类型不一样,因此invalid type
。为了使其工作,您需要将int
(已分配)的ARRAY复制到设备(静态长度)ARRAY int
(常量),例如:
__device__ __constant__ int dic[LEN];
来自CUDA C Programming Guide的示例(我建议您阅读 - 这非常好!):
__constant__ float constData[256];
float data[256];
cudaMemcpyToSymbol(constData, data, sizeof(data));
cudaMemcpyFromSymbol(data, constData, sizeof(data));
据我所知,您还可以cudaMemcpyToSymbol
指向指针的指针(与您的示例不同,您将数组复制到指针),但要注意指针将是常数,而不是它指向您设备的内存。如果您要使用此路线,则需要将cudaMalloc
,然后cudaMemcpyToSymbol
生成的ptr添加到设备内存中__constant__
设备var。 AGAIN,在这种情况下,数组值不会是常量 - 只有指向内存的指针才会是。
您对此案件的要求如下:
int * d_dic;
cudaMalloc((void **) &d_dic, num_codewords*(bSizeY*bSizeX)*sizeof(int));
cudaMemcpyToSymbol(c_dic_ptr, &d_Dic, sizeof(int *));
此外,您应该在调试内部错误检查逻辑中包装CUDA调用。我从talonmies借用了以下逻辑:
__inline __host__ void gpuAssert(cudaError_t code, char *file, int line,
bool abort=true)
{
if (code != cudaSuccess)
{
fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code),
file, line);
if (abort) exit(code);
}
}
#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }
要调用简单地将CUDA调用包装在其中,如下所示:
gpuErrchk(cudaMemcpyToSymbol(dic, flatDic, num_codewords*(bSizeY*bSizeX)*sizeof(int)));
如果您遇到分配问题或其他常见错误,编程将退出并显示错误消息。
要检查内核,请执行以下操作:
MyKernel<<<BLK,THRD>>>(vars...);
//Make sure nothing went wrong.
gpuErrchk(cudaPeekAtLastError());
gpuErrchk(cudaDeviceSynchronize());
感谢talonmies的错误检查代码!
注意:强>
即使你正在使用vanilla cudaMemcpy
,你的代码也会失败,因为你的数组没有cudaMalloc
内存 - 但是,在这种情况下,失败的可能是GPU相当于segfault(可能Unspecified launch failure
)因为指针会有一些垃圾值,你会尝试用该垃圾值给出的地址写入内存。