我对CUDA很新,我对一个对象的内存管理有疑问。我有一个对象函数将数据加载到设备,如果调用另一个对象函数,则执行计算。
我已经阅读了NVIDIA编程指南的一些部分和一些SO问题,但他们在一个功能中进行数据复制和计算,因此不需要多个功能。
更多规格: 数据被读取一次。我不知道编译时的数据大小,因此我需要动态分配。我当前的设备具有2.1的计算能力(将很快更新到6.1)。
我想在第一个函数中复制数据,并在不同的函数中使用数据。例如:
__constant__ int dev_size;
__device__ float* dev_data; //<- not sure about this
/* kernel */
__global__ void computeSomething(float* dev_output)
{
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx < dev_size)
{
dev_output[idx] = dev_data[idx]*100; // some computation;
}
}
// function 1
void OBJECT::copyVolumeToGPU(int size, float* data)
{
cudaMalloc(&dev_data, size * sizeof(float));
cudaMemcpy(dev_data, data, size * sizeof(float), cudaMemcpyHostToDevice );
cudaMemcpyToSymbol(dev_size, size, sizeof(int));
}
// function 2
void OBJECT::computeSmthOnDevice(int size)
{
// allocate output array
auto host_output = new float[size];
float* dev_output;
cudaMalloc(&dev_output, size * sizeof(float));
int block = 256;
int grid = ceil(size/block);
computeSomething<<<grid,block>>>(dev_output);
cudaMemcpy(host_output, dev_data, size * sizeof(float), cudaMemcpyDeviceToHost);
/* ... do something with output ... */
delete[] host_output;
cudaFree(dev_output);
}
gpuErrChk以这种方式执行:https://stackoverflow.com/a/14038590/3921660但在此示例中省略。
我可以使用__device__
指针(如__device__ float* dev_data;
)复制数据吗?
答案 0 :(得分:3)
一般来说,你的想法是可行的,但是这个:
cudaMalloc(&dev_data, size * sizeof(float));
不合法。在主机代码中获取__device__
项的地址是不合法的。因此,如果您在编译时知道大小,最简单的方法是将其转换为静态分配,例如
__device__ float dev_data[1000];
如果你真的想让它成为一个动态分配的__device__
指针,那么你将需要使用一个方法,如描述here,这涉及在典型的设备指针上使用cudaMalloc
在主机代码中是“临时”,然后通过__device__
将该“临时”指针复制到cudaMemcpyToSymbol
指针。然后,当您想通过cudaMemcpy
向/从特定分配中复制数据时,您可以使用cudaMemcpy
来自/来自主机代码的临时指针。
请注意,为了将数据从一个函数“传递”到下一个函数,或者将一个内核“传递”到下一个函数,没有理由不能只使用来自cudaMemcpy
的动态分配的指针,并将其传递给指向你需要它的地方。您甚至可以通过全局变量将它传递给任何需要它的主机函数,就像普通的全局指针一样。但是,对于内核,您仍然需要通过内核参数将这样的全局指针传递给内核。