【发布时间】:2016-01-18 05:25:38
【问题描述】:
鉴于此代码:
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 的“Achieved Occupancy”。对于最小的图像,Grid Size 为 [10,15,1],Block Size 为 [32, 16,1]。
【问题讨论】:
-
每个内核启动 150 个块。您的 GPU 必须有足够的可用资源才能安排来自另一个流的块。可以?这里有什么问题?
-
我有一台 GTX 980M,每个多处理器有 2048 个线程,每个块有 1024 个线程。我是否创建了如此多的线程或块,以至于一次只能运行一个内核 - 这就是 87% 的占用率告诉我的吗?
-
据我估计,您的 GPU 最多可以在每个 SMM 上运行 4 个块,而您的 GPU 中大约有 12 个 SMM。因此,您的并发块限制为 48。如果您的内核启动是 150 个块,则并非单个内核启动中的所有块都可以同时启动。多个内核启动同时运行的范围相当有限