我的工作使用4个流,我希望它们可以同时运行。代码是这样的:
for (int i=0; i<N; i++) //batch numbers
{
for (int j=0; j<4; j++)
myCudaCode(stream[j]); // working codes using the specified stream
}
但是,从nvvp profiler我看到流实际上并没有同时运行,因为CPU完全被内核启动占用。我没有使用任何cudaDeviceSynchronize。您可以从以下链接中看到该图。
据我所知,GPU上的所有内核都非常小,与CPU上的内核启动时间相当。但到目前为止,我们并不打算改变它们。从上图中,我看到CPU上的大多数内核启动大约需要5~10 us,这被认为是正常的。一批的整个处理时间约为0.4毫秒(如灰色所示)
优化代码的直观思维是使用多线程来并行化CPU上的CUDA内核启动。以下是我使用openMP所做的事情:
for (int i=0; i<N; i++)
{
#pragma omp parallel num_threads(4)
myCudaCode(stream[omp_get_thread_num()]);
}
现在nvvp探查器显示如下:
这四个流似乎同时运行。但是,对于每个CPU线程,CUDA内核的启动不再像以前那样紧凑,而且还会显着拉伸(通常为20~30 us)。一次批处理所需的时间(以灰色显示)现在大约为0.5ms,甚至比单线程情况更长。
我也试过pthread方法。它显示了类似的问题。
所以我想问一个有效的方法来平衡CPU上的内核启动。理想情况下,预计时间会减少四分之一。
我非常确定每个内核都足够小,远离完整的GPU计算资源。我正在使用Linux,i7 8核CPU和GTX 1070 GPU。
更新:根据我的实验,似乎使用多CPU线程根本不会减少总内核启动时间。假设用于处理N个流的单线程代码需要时间T,那么使用openMP和用于处理N个流的N线程代码(单线程用于单线程)也将近似需要时间T.如图所示,即使流现在看似并发,但每个内核启动延迟也变得很重要。有趣的是,总时间(对于一批或N个流)因此保持大致不变。
答案 0 :(得分:-1)
我认为你需要创建多个流。如果您使用cuda 7.0 +,请检查每线程默认流。
https://devblogs.nvidia.com/gpu-pro-tip-cuda-7-streams-simplify-concurrency/
查看上面的链接以获取详细示例。