理解CUDA中的动态并行性

时间:2015-06-11 11:24:59

标签: cuda dynamic-parallelism

动态并行的示例:

__global__ void nestedHelloWorld(int const iSize,int iDepth) {
    int tid = threadIdx.x;
    printf("Recursion=%d: Hello World from thread %d" "block %d\n",iDepth,tid,blockIdx.x);
    // condition to stop recursive execution
    if (iSize == 1) return;
    // reduce block size to half
    int nthreads = iSize>>1;
    // thread 0 launches child grid recursively
    if(tid == 0 && nthreads > 0) {
        nestedHelloWorld<<<1, nthreads>>>(nthreads,++iDepth);
        printf("-------> nested execution depth: %d\n",iDepth);
    }
}

使用一个块打印,两个块整个父网格已完成:

./nestedHelloWorld Execution Configuration: grid 1 block 8
Recursion=0: Hello World from thread 0 block 0
Recursion=0: Hello World from thread 1 block 0
Recursion=0: Hello World from thread 2 block 0
Recursion=0: Hello World from thread 3 block 0
Recursion=0: Hello World from thread 4 block 0
Recursion=0: Hello World from thread 5 block 0
Recursion=0: Hello World from thread 6 block 0
Recursion=0: Hello World from thread 7 block 0
-------> nested execution depth: 1
Recursion=1: Hello World from thread 0 block 0
Recursion=1: Hello World from thread 1 block 0
Recursion=1: Hello World from thread 2 block 0
Recursion=1: Hello World from thread 3 block 0
-------> nested execution depth: 2
Recursion=2: Hello World from thread 0 block 0
Recursion=2: Hello World from thread 1 block 0
-------> nested execution depth: 3
Recursion=3: Hello World from thread 0 block 0

假设我在threadIdx.x == 0的块中的一个线程中启动子网格。我是否可以假设父网格中的所有其他线程都已完成执行,直到我启动子网格为止?

如果是这样,这是如何工作的?我所读到的只是父网格在子网格之前没有在技术上完成。没有关于未启动子项的其他父线程的保证。

2 个答案:

答案 0 :(得分:4)

  

假设我从一个块中的一个线程启动一个子网格   threadIdx.x == 0。我可以假设父网格中的所有其他线程   已完成执行到我启动子网格的点   好?

没有。您不能假设父块中的其他线程或父网格中的其他块的状态。

  

如果是这样,这是如何工作的?所有我正在阅读的是父网格   在儿童网格之前没有技术上完成。关于保证没什么   没有启动子项的其他父线程。

当父线程启动子网格时,它会以高于自身的优先级将工作推送到GPU。在计算能力3.5 - 5.x上,GPU将安排最高优先级的工作,但它不会抢占任何正在运行的块。如果GPU已满,则计算工作分配将无法调度子块。当父块完成时,子块将在任何新的父块之前分发。此时设计仍然可以死锁。如果启动工作的块执行连接操作(cudaDeviceSynchronize)并且由于没有足够的空间来安排子工作或者它仍在运行,那么子工作尚未完成,那么父块(不是网格)将预先自己动手。这允许子网格进行前进。子网格完成后,CDP调度程序将恢复父块。

在父完成的所有块和所有子网格完成之前,父网格不会被标记为已完成。

  • 如果父网格启动子网格但未加入,则为 可能所有父块在子块之前完成 调度。
  • 如果父网格加入则很可能全部 子块网格在父块完成之前完成。
  • 如果父网格启动超过可以同时执行 GPU然后答案就在中间。

Nsight VSE CUDA Trace和Visual Profiler具有用于跟踪CDP网格的其他可视化工具。来自GTC 2013演示文稿Profiling and Optimizing CUDA Kernel Code with NVIDIA Nsight Visual Studio Edition的视频(但不是幻灯片)提供了有关CDP可视化的最佳文档。 17:15时开始观看。

答案 1 :(得分:0)

没有。 warp中的所有线程都以锁步方式执行,因此如果线程0尚未完成,则线程[1..31]都没有。块中的其他线程(或warp)可能已经或可能没有完成执行。