让我们在有父内核和子内核的地方使用以下代码。从所述父内核开始,我们希望在不同的流中启动threadIdx.x
子内核以最大化并行吞吐量。然后我们等待那些cudaDeviceSynchronize()
的子节点作为父内核需要查看对global
内存所做的更改。
现在假设我们还希望用流启动n
父内核,并且在我们希望并行启动的每组n
父内核之间,我们还必须使用{{1}等待结果}}
这会如何表现?
从this official introduction to Dynamic Parallelism by Nvidia我会认为cudaDeviceSynchronize()
只会等待在其中启动的流。它是否正确?如果没有,会发生什么?
注意:我知道只有这么多流可以一次运行(在我的情况下是32)但这更多是为了最大化占用
编辑:一些代码示例
parent kernel[0]
答案 0 :(得分:3)
在父内核完成之前,父内核将等待任何生成的子内核完成。这包含在dynamic parallelism documentation:
中子网格的调用和完成是正确嵌套的,这意味着在其线程创建的所有子网格都已完成之前,父网格不会被视为完成。即使调用的线程没有在启动的子网格上显式同步,运行时也保证父和子之间的隐式同步。
任何其他语义都应该可以从普通的流语义中推断出来,即:在发送到该流中的所有先前活动完成之前,启动到特定流中的活动才会开始。同样,在单独的流中启动的活动之间没有强制排序。
在您的示例中(或者实际上在任何示例中),父内核将等待,直到从该父内核启动的所有子内核都已完成,无论使用或未使用哪些流。
目前尚不清楚您是否在询问此问题,但请注意,对于示例中的设备代码,cudaDeviceSynchronize()
仅保证该线程将等待子内核完成,同样只强制执行结果可见性,为该线程订购。如果您希望同一块中的其他线程能够看到线程0生成的子内核的全局内存结果(只是为了选择一个示例),那么您可能希望在线程0中跟进cudaDeviceSynchronize()操作__syncthreads()
操作。在那个__syncthreads()
之后,同一个块中的其他线程将保证可以看到由线程0(或由任何线程启动的子内核,然后是cudaDeviceSynchronize()调用)启动的子内核产生的全局结果,在前面提到的__syncthreads()
)之前。
CDP环境中要注意的其他几个限制是nesting limit和pending launch limit。