假设我有一个带有设备指针并对其执行操作的函数。但是这个工作更适合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);
}
问题:
host_ptr
怎么办?我不想在这里引入不必要的cudaStreamSynchronize
。提前致谢。
答案 0 :(得分:4)
回答你的问题:
这是完成此任务的规范方法吗?
据我所知,这是唯一可以在没有显式同步调用的情况下完成此操作的方法。
如果我想在堆栈而不是堆上分配host_ptr
怎么办?我不想在这里引入不必要的cudaStreamSynchronize
。
你不会引入不必要的cudaStreamSynchronize
电话,你会引入一个必要的电话。在这种情况下,阻止堆栈变量超出范围的唯一方法是阻止,阻止的正确方法是调用cudaStreamSynchronize
。