【问题标题】:CUDA's cudaMemcpyToSymbol() throws "invalid argument" errorCUDA 的 cudaMemcpyToSymbol() 抛出“无效参数”错误
【发布时间】:2015-07-13 18:07:56
【问题描述】:

问题

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

[ERROR] 'main.cu' 中的'invalid argument' (11) 在'386'行

代码

已经开发了很多代码,所以我将简化我所拥有的。

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

__device__ __constant__ int* dic;

我还有一个宿主变量flatDic,它在main() 内部按以下方式分配:

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);

在调用cudaMemcpyToSymbol() 之前,我还尝试了cudaMalloc() dic 变量。 cudaMalloc() 中没有抛出错误,但 cudaMemcpyToSymbol() 错误仍然存​​在。

cudaMalloc((void **) &dic, num_codewords*(bSizeY*bSizeX)*sizeof(int));

我还通过网络、文档、论坛、示例等进行了广泛搜索,但均无济于事。

有人发现我的代码有什么问题吗?提前致谢。

【问题讨论】:

  • “我还通过网络、文档、论坛、示例等进行了广泛搜索,但均无济于事。” ...对于基本呼叫,请始终从 CUDA C 编程指南开始—— 1. 按 Ctrl + S 并在浏览器/PDF 阅读器中输入您正在查看的呼叫。 2. 阅读任何适用的内容并查看指南的代码示例。 3.如果#2失败了,才去论坛潜水。在这种情况下,指南中的信息是正确的,直接来自 NVIDIA——只是一些关于如何处理 CUDA API 调用问题的未来建议。
  • 我通常从参考指南开始,它以 HTML 格式提供。 Here's the CUDA 4.1 reference 谷歌的电话名称通常会出现这种情况。检查参考后,再检查编程指南。

标签: c cuda


【解决方案1】:

cudaMemcpyToSymbol 复制到一个常量变量,这里您尝试将多个 int 类型的字节(分配的数组)复制到 int * 类型的指针。这些类型不一样,因此是invalid type。要完成这项工作,您需要将int(已分配)的数组复制到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 指向指针的指针(与您的示例不同,您将数组复制到指针),但要注意只有 pointer 将是常量,不是它指向您设备上的内存。如果你要走这条路,你需要添加一个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 *));

此外,您应该在错误检查逻辑内部调试期间包装您的 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 提供错误检查代码!

注意:
即使你正在做一个普通的cudaMemcpy,你的代码也会失败,因为你的数组没有cudaMalloced 内存——不过,在这种情况下,失败可能是 GPU 相当于段错误(可能是@ 987654342@) 因为指针中会包含某种垃圾值,您将尝试使用该垃圾值给出的地址写入内存。

【讨论】:

    猜你喜欢
    • 2021-10-09
    • 2018-02-08
    • 1970-01-01
    • 2019-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多