CUDA cudaMemcpyFromSymbol“;无效的设备符号“;错误?
因此,我看到了一个关于如何使用CUDA cudaMemcpyFromSymbol“;无效的设备符号“;错误?,cuda,Cuda,因此,我看到了一个关于如何使用cudaMemcpyToSymbol从主机复制到GPU上的常量内存的问题 我的问题是如何做相反的操作,使用cudaMemcpyFromSymbol从设备常量内存复制到主机 在下面的最小可复制示例中,我得到 1) 无效的设备符号使用cudaMemcpyFromSymbol时出错(const_d_a,b,size),或 2) 如果我使用cudaMemcpyFromSymbol(&b,const\u d\u a,size,cudaMemcpyDeviceToHost),
cudaMemcpyToSymbol
从主机复制到GPU上的常量内存的问题
我的问题是如何做相反的操作,使用cudaMemcpyFromSymbol
从设备常量内存复制到主机
在下面的最小可复制示例中,我得到
- 1)
使用无效的设备符号
cudaMemcpyFromSymbol时出错(const_d_a,b,size)代码>,或
- 2) 如果我使用
cudaMemcpyFromSymbol(&b,const\u d\u a,size,cudaMemcpyDeviceToHost),则出现
分段错误
// a basic CUDA function to test working with device constant memory
#include <stdio.h>
#include <cuda.h>
const unsigned int N = 10; // size of vectors
__constant__ float const_d_a[N * sizeof(float)];
int main()
{
float * a, * b; // a and b are vectors. c is the result
a = (float *)calloc(N, sizeof(float));
b = (float *)calloc(N, sizeof(float));
/**************************** Exp 1: sequential ***************************/
int i;
int size = N * sizeof(float);
for (i = 0; i < N; i++){
a[i] = (float)i / 0.23 + 1;
}
// 1. copy a to constant memory
cudaError_t err = cudaMemcpyToSymbol(const_d_a, a, size);
if (err != cudaSuccess){
printf("%s in %s at line %d\n", cudaGetErrorString(err), __FILE__, __LINE__);
exit(EXIT_FAILURE);
}
cudaError_t err2 = cudaMemcpyFromSymbol(const_d_a, b, size);
if (err2 != cudaSuccess){
printf("%s in %s at line %d\n", cudaGetErrorString(err2), __FILE__, __LINE__);
exit(EXIT_FAILURE);
}
double checksum0, checksum1;
for (i = 0; i < N; i++){
checksum0 += a[i];
checksum1 += b[i];
}
printf("Checksum for elements in host memory is %f\n.", checksum0);
printf("Checksum for elements in constant memory is %f\n.", checksum1);
return 0;
}
//一个基本的CUDA函数,用于测试如何使用设备常量内存
#包括
#包括
常量无符号整数N=10;//向量大小
__常数浮点数常数[N*sizeof(float)];
int main()
{
float*a,*b;//a和b是向量。c是结果
a=(浮动*)calloc(N,sizeof(浮动));
b=(浮动*)calloc(N,sizeof(浮动));
/****************************实验1:顺序***************************/
int i;
int size=N*sizeof(浮点);
对于(i=0;i
在CUDA中,各种cudaMemcpy*
操作都是按照C标准库memcpy
例程建模的。在该函数中,第一个指针是始终目标指针,第二个指针是始终源指针。所有cudaMemcpy*
函数也是如此
因此,如果要执行cudaMemcpyToSymbol
,则符号最好是传递给函数的第一个(目标)参数(第二个参数将是主机指针)。如果要执行cudaMemcpyFromSymbol
,则符号必须是第二个参数(源位置),主机指针是第一个参数。这不是你在这里看到的:
cudaError_t err2 = cudaMemcpyFromSymbol(const_d_a, b, size);
^ ^
| This should be the symbol.
|
This is supposed to be the host destination pointer.
您可以通过查看来发现这一点
如果我们颠倒该行代码中这两个参数的顺序:
cudaError_t err2 = cudaMemcpyFromSymbol(b, const_d_a, size);
您的代码将无错误运行,并且打印的最终结果将匹配
这些函数中的a
或b
指针都不需要使用与符号<代码>a和b
已经是指针。在链接的示例中,pi\u gpu\u h
不是指针。它是一个普通变量。要使用cudaMemcpyFromSymbol
将某些内容复制到它,必须获取该普通变量的地址,因为函数需要一个(目标)指针
顺便说一句,这看起来不太对:
__constant__ float const_d_a[N * sizeof(float)];
这是一个有效的静态数组声明,除了N
数量,则无需在此处将float
乘以N
。只要sizeof(float)
本身就可以做到:N
__constant__ float const_d_a[N];
然而,保持原样并不会给您发布的代码带来问题 谢谢你及时的回复,罗伯特!很清楚,我现在明白我错在哪里了。对于我链接的示例,用户建议我们使用
cudaMemcpyFromSymbol(&pi\u gpu\u h,pi\u gpu,sizeof(double),cudaMemcpyDeviceToHost)
,我想这个界面已经过时了?因为我们不需要最后的参数。也感谢您指出我在数组声明中的额外sizeof(float)
规范。这可能解决了我在另一段代码中遇到的另一个bug。我将这个数组声明与需要指定确切字节数的malloc
函数弄错了。谢谢如果您研究我链接的文档,您会发现这里有默认参数。函数的默认参数不是CUDA特定的概念,可以通过C++学习来了解它。由于存在默认参数,因此可以提供或省略它们。但是,您链接的示例确实包含错误。它与所提供参数的顺序有关。不过,我不会在评论的空间里解释。我已经纠正了你链接的问题的答案。错误的本质是描述感谢提示!我现在了解到1)cudaMemcpyDeviceToHost参数设置为默认值,2)原始答案缺少偏移参数,因此顺序有问题。