Memory CUDA中全局内存与常量内存的使用

Memory CUDA中全局内存与常量内存的使用,memory,cuda,Memory,Cuda,嘿,那里, 我有以下代码: #if USE_CONST == 1 __constant__ double PNT[ SIZE ]; #else __device__ double *PNT; #endif 过了一会儿,我有: #if USE_CONST == 0 cudaMalloc((void **)&PNT, sizeof(double)*SIZE); cudaMemcpy(PNT, point, sizeof(double)*SIZE, c

嘿,那里, 我有以下代码:

#if USE_CONST == 1
    __constant__ double PNT[ SIZE ];    
#else
    __device__ double *PNT;
#endif
过了一会儿,我有:

#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
然而,
在前面的代码中有定义。当使用
时,使用_CONST=1
一切都能按预期工作,但如果不使用它,则不会。我通过访问内核函数中的数组

PNT[索引]

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

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

cudaMemcpyToSymbol("PNT", point, sizeof(double)*SIZE)
或者:

double *cpnt;
cudaGetSymbolAddress((void **)&cpnt, "PNT");
cudaMemcpy(cpnt, point, sizeof(double)*SIZE, cudaMemcpyHostToDevice);
如果您计划多次从主机API访问符号,那么这可能会快一点

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

double *gpnt;
cudaGetSymbolAddress((void **)&gpnt, "PNT");
cudaMemcpy(gpnt, point, sizeof(double)*SIZE.  cudaMemcpyHostToDevice););

虽然这是一个老问题,但我还是为未来的谷歌用户补充了这个问题:

问题在于:

cudaMalloc((void **)&PNT, sizeof(double)*SIZE);
cudaMemcpy(PNT, point, sizeof(double)*SIZE, cudaMemcpyHostToDevice);
cudamaloc
写入主机版本的
PNT
,这实际上是一个不能从主机访问的设备变量。正确的做法是分配内存,将地址复制到设备符号,并将内存复制到该符号指向的内存:

void* memPtr;
cudaMalloc(&memPtr, sizeof(double)*SIZE);
cudaMemcpyToSymbol(PNT, &memPtr, sizeof(memPtr));
// In other places you'll need an additional:
// cudaMemcpyFromSymbol(&memPtr, PNT, sizeof(memPtr));
cudaMemcpy(memPtr, point, sizeof(double)*SIZE, cudaMemcpyHostToDevice);
更容易的办法是:

#if USE_CONST == 1
    __constant__ double PNT[ SIZE ];    
#else
    __device__ double PNT[ SIZE ];
#endif

// No #if required anymore:
cudaMemcpyToSymbol(PNT, point, sizeof(double)*SIZE);

好的,首先谢谢。奇怪的是,它在没有引语的情况下工作。。。但我要求的是在没有
USE_CONST=1
时的访问,这意味着使用带有全局内存的块<代码>\uuuu设备\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu等。。。然后它就不正确了:(有什么不对吗?Talonmes关于如何做的回答是正确的(所以我投了赞成票),但它缺乏解释。解释是:
*PNT
是一个
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu设备变量,而不是一个包含设备变量地址的主机变量。(我知道这很混乱。)因此,如果您试图通过
(void**)和PNT在主机上访问它,则您试图从主机读取一个不允许的设备变量。从主机代码的角度来看,它只是一个符号,因此您需要使用
cudaGetSympolAddress()
将设备地址存储在主机变量中,然后您可以将其传递给@talonmies所示的
cudaMemcpyToSymbol()。此处显示的用法无法正确使用!
cudaMemcpyToSymbol
的使用已经使用了
cudaGetSymbolAddress
,因此两次使用它可能会打破访问越界的情况。未初始化的常量内存设置为0,因为它在全局空间中未定义。