cuda streams:在流执行后没有调用回调

时间:2015-04-10 16:28:30

标签: c++ cuda callback

我遇到了cuda stream回调函数的问题。问题是它在内核运行后不会执行。我将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()执行callback_function()。内核由主机多次执行,并且在完成后它永远不会执行回调函数。我可以看到内核已成功执行但回调永远不会到来。

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

1 个答案:

答案 0 :(得分:6)

我认为您可能对回调如何运作感到困惑。通常,当您向CUDA流发出CUDA操作时,如果已完成向该流发出的所有前面的CUDA活动(以及在开始向该流发出的任何后续活动之前),则执行该CUDA操作。

回调也不例外。如果要在内核执行后执行回调,则必须在发出内核后向该流发出回调。 add callback函数的定义是 not

  

"只要内核在此流中完成,就运行此回调"

definition of the add callback function

  

"当CUDA流完成到目前为止的所有CUDA活动时,然后执行回调"

或直接引用文档:

  

完成前一个流操作后调用的功能

因此,这个构造函数对我没有意义:

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

这个构造函数说:

"创建CUDA流"

"当此流的所有先前发布的活动完成后,运行此回调"

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

  

"所以在执行运行功能"

之前注册此回调

不,如果这是你想要的:

  

问题是它在内核运行后没有执行

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