CUDA的cudaMemcpyToSymbol()抛出"无效参数"错误

Tel*_*ues 5 c cuda

问题

我正在尝试将int数组复制到设备的常量内存中,但我不断收到以下错误:

[错误]'无效参数'(11)在'main.cu'第'386行'

代码

开发了很多代码,所以我将简化我的工作.

我在__constant__main.cu文件的顶部声明了一个设备变量,在任何函数之外.

__device__ __constant__ int* dic;
Run Code Online (Sandbox Code Playgroud)

我也有一个宿主变量,flatDic它是以下面的方式进行malloc,内部main():

int* flatDic = (int *)malloc(num_codewords*(bSizeY*bSizeX)*sizeof(int));
Run Code Online (Sandbox Code Playgroud)

然后我尝试的内容复制flatDicdic通过这样做,也是在main():

cudaMemcpyToSymbol(dic, flatDic, num_codewords*(bSizeY*bSizeX)*sizeof(int));
Run Code Online (Sandbox Code Playgroud)

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);
Run Code Online (Sandbox Code Playgroud)

在调用之前我也尝试过cudaMalloc()这个dic变量cudaMemcpyToSymbol().不会引发任何错误cudaMalloc(),但cudaMemcpyToSymbol()错误仍然存​​在.

cudaMalloc((void **) &dic, num_codewords*(bSizeY*bSizeX)*sizeof(int));
Run Code Online (Sandbox Code Playgroud)

我也广泛搜索网络,文档,论坛,示例等,但都无济于事.

有人看到我的代码有什么问题吗?提前致谢.

Jas*_*ick 6

cudaMemcpyToSymbol复制到常量变量,这里您尝试将类型的多个字节int(分配的 ARRAY)复制到类型的指针int *。这些类型并不相同,因此invalid type. 要实现此功能,您需要将int(已分配)的数组复制到(常量)的设备(静态长度)数组int,例如:

__device__ __constant__ int dic[LEN];
Run Code Online (Sandbox Code Playgroud)

CUDA C 编程指南中的示例(我建议您阅读——非常好!):

__constant__ float constData[256];
float data[256];
cudaMemcpyToSymbol(constData, data, sizeof(data));
cudaMemcpyFromSymbol(data, constData, sizeof(data));
Run Code Online (Sandbox Code Playgroud)

据我所知,您还可以使用cudaMemcpyToSymbol指向指针的指针(与您的示例不同,您将数组复制到指针),但请注意该指针将是常量,而不是它指向设备上的内存。如果您打算走这条路线,则需要添加一个cudaMalloc,然后cudaMemcpyToSymbol将生成的 ptr 到设备内存添加到您的__constant__设备变量中。同样,在这种情况下,数组值将不是常量——只有指向内存的指针才是常量。

您对本案的要求如下:

int * d_dic;
cudaMalloc((void **) &d_dic, num_codewords*(bSizeY*bSizeX)*sizeof(int));
cudaMemcpyToSymbol(c_dic_ptr, &d_Dic, sizeof(int *));
Run Code Online (Sandbox Code Playgroud)

此外,您还应该在调试期间将 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__); }
Run Code Online (Sandbox Code Playgroud)

要调用,只需将 CUDA 调用包装在其中,如下所示:

gpuErrchk(cudaMemcpyToSymbol(dic, flatDic, num_codewords*(bSizeY*bSizeX)*sizeof(int)));
Run Code Online (Sandbox Code Playgroud)

如果您遇到分配问题或其他常见错误,编程将退出并显示错误消息。

要检查您的内核,请执行以下操作:

MyKernel<<<BLK,THRD>>>(vars...);

//Make sure nothing went wrong.
gpuErrchk(cudaPeekAtLastError());
gpuErrchk(cudaDeviceSynchronize());
Run Code Online (Sandbox Code Playgroud)

感谢talonmies提供的错误检查代码!

注意:
即使您正在执行 vanilla 操作cudaMemcpy,您的代码也会失败,因为您没有cudaMalloc为数组分配内存 - 但在这种情况下,失败可能是 GPU 相当于段错误(可能Unspecified launch failure),就像指针一样其中有某种垃圾值,您将尝试使用该垃圾值给出的地址写入内存。