【发布时间】:2016-07-19 06:19:45
【问题描述】:
对于我目前正在开发的应用程序,我希望有一个长内核(即相对于其他内核需要很长时间才能完成的内核)与一系列同时运行的多个较短内核同时执行.然而,更复杂的是,四个较短的内核在完成后都需要同步,以便执行另一个短内核来收集和处理其他短内核输出的数据。
以下是我想到的示意图,带有编号的绿色条代表不同的内核:
为了实现这一点,我编写了如下代码:
// definitions of kernels 1-6
class Calc
{
Calc()
{
// ...
cudaStream_t stream[5];
for(int i=0; i<5; i++) cudaStreamCreate(&stream[i]);
// ...
}
~Calc()
{
// ...
for(int i=0; i<5; i++) cudaStreamDestroy(stream[i]);
// ...
}
void compute()
{
kernel1<<<32, 32, 0, stream[0]>>>(...);
for(int i=0; i<20; i++) // this 20 is a constant throughout the program
{
kernel2<<<1, 32, 0, stream[1]>>>(...);
kernel3<<<1, 32, 0, stream[2]>>>(...);
kernel4<<<1, 32, 0, stream[3]>>>(...);
kernel5<<<1, 32, 0, stream[4]>>>(...);
// ?? synchronisation ??
kernel6<<<1, 32, 0, stream[1]>>>(...);
}
}
}
int main()
{
// preparation
Calc C;
// run compute-heavy function as many times as needed
for(int i=0; i<100; i++)
{
C.compute();
}
// ...
return 0;
}
注意:块、线程和共享内存的数量只是任意数字。
现在,我将如何在每次迭代时正确同步内核 2-5?一方面,我不知道哪个内核需要最长时间才能完成,因为这可能取决于用户输入。此外,我尝试过使用cudaDeviceSynchronize() 和cudaStreamSynchronize(),但它们的总执行时间增加了三倍多。
Cuda 事件可能是要走的路吗?如果是这样,我应该如何应用它们?如果不是,那么正确的方法是什么?
非常感谢。
【问题讨论】: