CUDA 的 cudaMemcpyToSymbol() 抛出 "invalid argument"错误

标签 c cuda

问题

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

[ERROR] 'invalid argument' (11) in 'main.cu' at line '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));

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

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

最佳答案

cudaMemcpyToSymbol 复制到一个常量变量,在这里你试图复制多个 int 类型的字节(一个分配的数组)到一个 int 类型的指针*。这些类型不同,因此是无效类型。要使其工作,您需要将 int 的 ARRAY(已分配)复制到 int 的设备(静态长度)ARRAY(常量),例如:

__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__ 设备变种。同样,在这种情况下,数组值不会是常量——只有指向内存的指针才是常量。

你对这个案例的要求是这样的:

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,您的代码也会失败,因为您没有为您的数组 cudaMalloc 编辑内存——不过,在那种情况下,失败很可能是 GPU 等同于段错误(可能是 Unspecified launch failure),因为指针中会有某种垃圾值,您将尝试使用该垃圾值给出的地址写入内存。

关于CUDA 的 cudaMemcpyToSymbol() 抛出 "invalid argument"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9676441/

相关文章:

c - 尝试消除共轭梯度内核中的 cudaDeviceSynchronize()

cuda - 用于 GPU 编程的 DirectCompute 与 OpenCL?

c - Linux 的 GCC 替代方案,支持 OpenMP 和带 +、-、*、/和 % 的 128 位整数

c - 我不明白使用 pthread_key_create 的原因,你能告诉我为什么吗?

c - 使用 getline() C 时出现段错误

performance - Pytorch 中的 Titan XP 与 Quadro P400 GPU

c++ - 编译似乎不遵循不同 operator= 重载之间的正确路径

cuda - 令人困惑的 cuda 版本

c - 程序集 MMX 点积段错误

c:将字符串传递给函数失败