花一些时间专注于 NVIDIA 提供的大量文档。
从编程指南:
float* devPtr;
cudaMalloc((void**)&devPtr, 256 * sizeof(*devPtr));
cudaMemset(devPtr, 0, 256 * sizeof(*devPtr));
这是一个如何分配内存的简单示例。现在,在您的内核中,您应该接受一个指向浮点数的指针,如下所示:
__global__
void kernel1(float *some_neat_data)
{
some_neat_data[threadIdx.x]++;
}
__global__
void kernel2(float *potentially_that_same_neat_data)
{
potentially_that_same_neat_data[threadIdx.x] *= 0.3f;
}
所以现在你可以像这样调用它们:
float* devPtr;
cudaMalloc((void**)&devPtr, 256 * sizeof(*devPtr));
cudaMemset(devPtr, 0, 256 * sizeof(*devPtr));
kernel1<<<1,128>>>(devPtr);
kernel2<<<1,128>>>(devPtr);
由于这些数据用于许多功能,我希望它是全球性的。
使用全局变量的充分理由很少。这绝对不是一个。我将把它作为一个练习来扩展这个例子,包括将“devPtr”移动到全局范围。
编辑:
好的,根本问题是这样的:您的内核只能访问设备内存,并且它们可以使用的唯一全局范围指针是 GPU 指针。从 CPU 调用内核时,在幕后发生的事情是指针和原语在内核执行之前被复制到 GPU 寄存器和/或共享内存中。
所以我能建议的最接近的是:使用 cudaMemcpyToSymbol() 来实现你的目标。但是,在后台,考虑另一种方法可能是正确的事情。
#include <algorithm>
__constant__ float devPtr[1024];
__global__
void kernel1(float *some_neat_data)
{
some_neat_data[threadIdx.x] = devPtr[0] * devPtr[1];
}
__global__
void kernel2(float *potentially_that_same_neat_data)
{
potentially_that_same_neat_data[threadIdx.x] *= devPtr[2];
}
int main(int argc, char *argv[])
{
float some_data[256];
for (int i = 0; i < sizeof(some_data) / sizeof(some_data[0]); i++)
{
some_data[i] = i * 2;
}
cudaMemcpyToSymbol(devPtr, some_data, std::min(sizeof(some_data), sizeof(devPtr) ));
float* otherDevPtr;
cudaMalloc((void**)&otherDevPtr, 256 * sizeof(*otherDevPtr));
cudaMemset(otherDevPtr, 0, 256 * sizeof(*otherDevPtr));
kernel1<<<1,128>>>(otherDevPtr);
kernel2<<<1,128>>>(otherDevPtr);
return 0;
}
在这个例子中不要忘记'--host-compilation=c++'。