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

Canonical ways to perform host-side malloc and asynchronous host-to-device memcpy

本文关键字:主机 范方法 方法 memcpy malloc 异步 执行      更新时间:2023-10-16

>假设我有一个函数,它接受设备指针并在其上执行某些操作。但是,该作业更适合 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

提前谢谢。

要回答您的问题:

  1. 这是完成此任务的规范方法吗?
    据我所知,这是无需显式同步调用即可做到这一点的唯一方法。

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