cuda设备变量在不同功能中的分配和使用

时间:2017-05-19 12:56:15

标签: memory-management cuda gpu

我对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;)复制数据吗?

1 个答案:

答案 0 :(得分:3)

一般来说,你的想法是可行的,但是这个:

cudaMalloc(&dev_data, size * sizeof(float));

不合法。在主机代码中获取__device__项的地址是不合法的。因此,如果您在编译时知道大小,最简单的方法是将其转换为静态分配,例如

__device__ float dev_data[1000]; 

如果你真的想让它成为一个动态分配的__device__指针,那么你将需要使用一个方法,如描述here,这涉及在典型的设备指针上使用cudaMalloc在主机代码中是“临时”,然后通过__device__将该“临时”指针复制到cudaMemcpyToSymbol指针。然后,当您想通过cudaMemcpy向/从特定分配中复制数据时,您可以使用cudaMemcpy来自/来自主机代码的临时指针。

请注意,为了将数据从一个函数“传递”到下一个函数,或者将一个内核“传递”到下一个函数,没有理由不能只使用来自cudaMemcpy的动态分配的指针,并将其传递给指向你需要它的地方。您甚至可以通过全局变量将它传递给任何需要它的主机函数,就像普通的全局指针一样。但是,对于内核,您仍然需要通过内核参数将这样的全局指针传递给内核。