两个连续的内核还是全网格协作组同步?

时间:2019-01-08 00:14:53

标签: performance cuda gpu-cooperative-groups

假设我有两个任务要在GPU上运行,第二个任务基本上依赖第一个任务的所有工作。传统上,我基本上必须将这些任务编写为两个单独的内核,并安排第二个在第一个之后的某个时刻运行。但是-使用CUDA 9,我现在可以在整个网格上进行同步,以完成其在第一个任务上的工作-using the cooperative groups feature,然后继续让网格执行第二个任务。

我的问题是:

  • 我们能否提供一个关于何时编写更好的性能,编写两个内核的性能以及何时使用全网格同步的经验法则?
  • 如果是这样,那会是什么?
  • 如果不是-为什么在哪种情况下很难确定哪个更合适?

1 个答案:

答案 0 :(得分:2)

将此作为CW答案,以便其他人可以随意添加自己的意见并进行编辑。

grid-wide sync feature in cooperative groups附带了一项要求,以将线程补数(网格的大小)限制为所运行的GPU的承载能力。这不是主要的性能限制因素,但是它要求您编写可灵活使用不同网格大小同时仍能实现最大性能的代码。 grid-stride loops是这种编码策略的典型组成部分。

因此,网格范围的同步功能通常需要仔细的编码和额外的代码开销(例如,使用占用API),以实现最佳性能,尤其是与简单或幼稚的内核相比。

要抵消程序员生产率的这种可能降低,一些可能的好处是:

  1. 在启动开销占整个运行时很重要的情况下,协作式网格范围的同步可能会带来很大的好处。除了2个独立内核的融合之外,由于可以有效地将启动循环“移至GPU”,因此可以在循环中调用内核的算法(例如jacobi迭代/松弛)或其他时间步仿真算法可能会明显受益,用单个内核调用替换内核启动循环。

  2. 在存在大量片上“状态”(例如寄存器内容,共享内存内容)的情况下,需要在网格范围同步之前加载该“状态”,并在此之后使用在整个网格范围内进行同步之后,协作组可能会大获成功,从而节省了内核时间,而该时间本可以用于重新加载状态的网格范围同步。例如,这似乎是动机here(请参见第4.3节)。我并不是在建议他们使用合作社团体(不是)。我建议他们有动力使用当时可用的临时方法来寻求网格范围的同步,以消除状态重载的成本以及内核启动开销的成本。