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),则出现
    分段错误
我已经咨询了那个些建议我按1)编码的人,那个些建议我按2)编码的人。他们两个都不在这里工作

有谁能帮忙建议解决这个问题的方法吗?我一定是理解不正确。。。谢谢

代码如下:

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

这是一个有效的静态数组声明,除了Y.StangtSux装饰器,它应该等价于在C或C++中如何实现它。如果要存储

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)原始答案缺少偏移参数,因此顺序有问题。