繁体   English   中英

CUDA流未并行运行

[英]CUDA streams not running in parallel

给出以下代码:

void foo(cv::gpu::GpuMat const &src, cv::gpu::GpuMat *dst[], cv::Size const dst_size[], size_t numImages)
{
    cudaStream_t streams[numImages];
    for (size_t image = 0; image < numImages; ++image)
    {
        cudaStreamCreateWithFlags(&streams[image], cudaStreamNonBlocking);
        dim3 Threads(32, 16);
        dim3 Blocks((dst_size[image].width + Threads.x - 1)/Threads.x,
                    (dst_size[image].height + Threads.y - 1)/Threads.y);
        myKernel<<<Blocks, Threads, 0, streams[image]>>>(src, dst[image], dst_size[image]);
    }
    for (size_t image = 0; image < numImages; ++image)
    {
        cudaStreamSynchronize(streams[image]);
        cudaStreamDestroy(streams[image]);
    }
}

查看nvvp的输出,即使第一个流是一个漫长的过程,其他流也应该能够与之重叠,但是我几乎可以完美地执行串行执行。

请注意,我的内核使用30个寄存器,并且所有内核都报告“已实现占用率”约为0.87。 对于最小的图像,网格大小为[10,15,1],块大小为[32,16,1]。

CUDA编程指南( 链接 )中给出了描述并发内核执行限制的条件,但要点是,只有在GPU有足够资源来运行GPU的情况下,GPU才可能运行来自不同流的多个内核。

在您的用例中,您曾说过正在运行一个内核的多个启动,每个内核有150个512个线程的块。 您的GPU有12个SMM(我认为),并且每个SMM 最多可以同时运行4个块(4 * 512 = 2048个线程,这是SMM的限制)。 因此您的GPU最多只能同时运行4 * 12 = 48个块。 当在命令管道中多次启动包含150个块的启动时,似乎几乎没有(也许甚至没有)并发执行内核的机会。

如果通过减小块大小来增加内核的调度粒度,则可能能够鼓励内核执行重叠。 与较大的块相比,较小的块更有可能找到可用资源和调度时隙。 同样,减少每次内核启动的总块数(可能通过增加每个线程的并行工作量) 也可能有助于增加多个内核重叠或并行执行的可能性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM