cuda流:流执行后未调用回调

cuda streams: callback not getting called after stream execution

本文关键字:调用 回调 执行 cuda      更新时间:2023-10-16

我在使用cuda流回调函数时遇到问题。问题是它在内核运行后不会执行。我将cuda流封装在一个C++类中,如下所示:

class Stream
{
public:
Stream();
void run(float *input, int points);
~Stream();
static void CUDART_CB callback(cudaStream_t stream,
cudaError_t status,
void * user_data);
private:
void callback_function();
cudaStream_t s;
};

现在,我有了回调函数设置,如前所述,如下所示:

void CUDART_CB StreamWorkflow::callback(cudaStream_t stream,
cudaError_t status,
void * user_data)
{
Stream* thiz = (Stream *)(user_data);
thiz->callback_function();
}

构造函数设置流并附加回调

Stream::Stream()
{
checkCudaErrors(cudaStreamCreate(&s));
checkCudaErrors(cudaStreamAddCallback(s, Stream::callback, this, 0));
}

现在run方法在这个流上调用cuda内核,我知道它执行得很好。它的实现方式如下:

void Stream::run(float *f, int p)
{
dim3 block(16, 16);
dim3 grid((int)ceil(double(p) / 256.0));
my_kernel(f, p, grid, block, s);
checkCudaErrors(cudaDeviceSynchronize());
getLastCudaError("kernel launch failed");
}

我的问题是回调只有在构造函数被执行时才会被调用。因此,一旦创建了对象,callback_function()就会通过注册的callback()执行。内核被主机多次执行,并且在完成时从不执行回调函数。我可以看到内核执行成功,但回调从未到来。

每次运行内核时,我都必须注册回调(所以在执行run函数之前注册此回调),还是我在这里真的做错了什么?

我想您可能对回调的工作方式感到困惑。通常,当向CUDA流发出CUDA操作时,该CUDA操作将在向该流发出的所有先前CUDA活动都已完成时(以及在开始向该流发送的任何后续活动之前)执行。

回调也不例外。如果您希望在内核执行后执行回调,那么您必须在发出内核后向该流发出回调。添加回调函数的定义是而不是

"任何时候内核在这个流中完成,运行这个回调">

添加回调函数的定义是:

"当CUDA流至此完成所有CUDA活动时,执行回调">

或者,直接从文档中引用:

在前面的流操作完成后调用的函数

因此,这个构造函数对我来说毫无意义:

Stream::Stream()
{
checkCudaErrors(cudaStreamCreate(&s));
checkCudaErrors(cudaStreamAddCallback(s, Stream::callback, this, 0));
}

这个构造函数说:

"创建CUDA流">

"当以前向该流发出的所有活动都完成时,运行此回调">

但当然,您还没有向该流发出任何活动,因此回调会在流创建后立即运行(并且只运行一次)。

"所以在执行运行函数之前注册此回调">

不,如果这是你想要的:

问题是在内核运行后它不会执行

然后在内核启动之后将添加回调函数移动到,我认为您更有可能看到所需的活动。