问题
我试图将 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/