规范方法来执行主机端malloc和异步主机到设备memcpy

时间:2016-01-22 07:50:56

标签: c++ asynchronous cuda

假设我有一个带有设备指针并对其执行操作的函数。但是这个工作更适合cpu,所以我在cpu上分配一块内存,对cpu内存执行一些操作,然后将其复制到gpu。像这样:

void func(void *dev_ptr, cudaStream_t stream)
{
    void *host_ptr = malloc(100);
    // do something on host_ptr
    cudaMemcpyAsync(dev_ptr, host_ptr, 100, cudaMemcpyHostToDevice, stream);
    free(host_ptr);
}

此处free调用很危险,因为memcpy是异步的,并且调用点free时可能无法完成复制。我发现CUDA中有一个回调机制,所以我认为以下代码可能更合适:

void CUDART_CB callback_free(cudaStream_t, cudaError_t, void *userData)
{
    free(userData);
}

void func(void *dev_ptr, cudaStream_t stream)
{
    void *host_ptr = malloc(100);
    // do something on host_ptr
    cudaMemcpyAsync(dev_ptr, host_ptr, 100, cudaMemcpyHostToDevice, stream);
    cudaStreamAddCallback(stream, callback_free, static_cast<void *>(host_ptr), 0);
}

问题:

  1. 这是完成此任务的规范方法吗?
  2. 如果我希望在堆栈而不是堆上分配host_ptr怎么办?我不想在这里引入不必要的cudaStreamSynchronize
  3. 提前致谢。

1 个答案:

答案 0 :(得分:4)

回答你的问题:

  1. 这是完成此任务的规范方法吗?
    据我所知,这是唯一可以在没有显式同步调用的情况下完成此操作的方法。

  2. 如果我想在堆栈而不是堆上分配host_ptr怎么办?我不想在这里引入不必要的cudaStreamSynchronize
    你不会引入不必要的cudaStreamSynchronize电话,你会引入一个必要的电话。在这种情况下,阻止堆栈变量超出范围的唯一方法是阻止,阻止的正确方法是调用cudaStreamSynchronize