在CUDA中使用全局与常量内存

tim*_*tim 5 memory cuda

嘿那里,我有以下代码:

#if USE_CONST == 1
    __constant__ double PNT[ SIZE ];    
#else
    __device__ double *PNT;
#endif
Run Code Online (Sandbox Code Playgroud)

稍后我有:

#if USE_CONST == 0
    cudaMalloc((void **)&PNT, sizeof(double)*SIZE);
    cudaMemcpy(PNT, point, sizeof(double)*SIZE, cudaMemcpyHostToDevice);
#else
    cudaMemcpyToSymbol(PNT, point, sizeof(double)*SIZE);
#endif
Run Code Online (Sandbox Code Playgroud)

point在之前的代码中定义的地方.当处理USE_CONST=1所有事情按预期工作时,但在没有它的情况下工作,而不是工作.我通过我的内核函数访问数组

PNT[ index ]

这两种变体之间的问题在哪里?谢谢!

tal*_*ies 3

CUDA 4.0之前的cudaMemcpyToSymbol的正确用法是:

cudaMemcpyToSymbol("PNT", point, sizeof(double)*SIZE)
Run Code Online (Sandbox Code Playgroud)

或者:

double *cpnt;
cudaGetSymbolAddress((void **)&cpnt, "PNT");
cudaMemcpy(cpnt, point, sizeof(double)*SIZE, cudaMemcpyHostToDevice);
Run Code Online (Sandbox Code Playgroud)

如果您计划多次从主机 API 访问符号,这可能会更快一些。

编辑:误解了这个问题。对于全局内存版本,执行与恒定内存的第二个版本类似的操作

double *gpnt;
cudaGetSymbolAddress((void **)&gpnt, "PNT");
cudaMemcpy(gpnt, point, sizeof(double)*SIZE.  cudaMemcpyHostToDevice););
Run Code Online (Sandbox Code Playgroud)

  • talonmies 关于如何做到这一点的答案是正确的(所以我投了赞成票),但缺乏解释。解释是:`*PNT`是一个`__device__`变量,而不是包含设备变量地址的主机变量。(我知道这很令人困惑。)因此,如果您尝试在主机上使用“(void**)&PNT”访问它,您将尝试从主机读取不允许的设备变量。从主机代码的角度来看,它只是一个符号,因此您需要使用“cudaGetSympolAddress()”将设备地址存储在主机变量中,然后可以将其传递给“cudaMemcpyToSymbol()”,如 @talonmies 所示。 (5认同)
  • 对于未来的读者:字符串版本已被弃用,这就是为什么不带引号的版本可以工作(并且是首选)。此处所示的用法将无法正常工作!“cudaMemcpyToSymbol”的用法已经使用了“cudaGetSymbolAddress”,因此使用它两次将会中断 (2认同)