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

cuda streams: callback not getting called after stream execution

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

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));
}

现在 运行 方法在此流上调用 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() 就会通过注册的回调 () 执行。内核被主机执行多次,并且在完成时从不执行回调函数。我可以看到内核已成功执行,但回调从未到来。

每次 内核 运行 时,我是否必须注册回调 (因此在执行 运行 函数之前注册此回调)或者我在做什么这里真的有问题吗?

我想您可能对回调的工作原理感到困惑。通常,当您向 CUDA 流发出 CUDA 操作时,该 CUDA 操作将在所有先前向该流发出的 CUDA activity 已完成时执行(并且在向该流发出任何后续 activity 之前)开始)。

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

"any time a kernel completes in this stream, run this callback"

definition of the add callback function :

"when the CUDA stream has completed all CUDA activity up to this point, then execute the callback"

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

The function to call once preceding stream operations are complete

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

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

这个构造函数说:

"create a CUDA stream"

"when all previously issued activity to this stream is complete, run this callback"

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

"so register this callback before executing the run function"

不,如果这是你想要的:

The problem is that it does not execute after the kernel is run

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