用于多个内核的Cuda Stream Processing消歧

时间:2013-02-20 12:49:03

标签: concurrency cuda cuda-streams

关于多内核的Cuda流处理的一些问题。 假设在具有3.5的kepler设备中的流和内核,其中s <= 32。 kernel使用大小为n的dev_input数组和大小为s * n的dev输出数组。 内核从输入数组中读取数据,将其值存储在寄存器中,对其进行操作并将其结果写回位于s * n + tid的dev_output。

我们的目标是每次使用n个流中的一个来运行相同的内核。与simpleHyperQ示例类似。你能否评论以下任何一项是否以及如何影响并发?

  1. dev_input和dev_output未固定;
  2. dev_input,因为它是vs dev_input size s * n,其中每个内核读取唯一数据(没有读取冲突)
  3. 内核从常量内存中读取数据
  4. 每个块分配10kb的共享内存。
  5. 内核使用60个寄存器
  6. 任何好评都将不胜感激...... !!!

    欢呼声, Thanasio

    罗伯特, 非常感谢您的详细解答。这非常有帮助。我编辑了4,每块10kb。所以在我的情况下,我发布了61个块和256个线程的网格。内核受计算限制。我启动了8个相同内核的流。描述它们然后我看到前两个之间非常好的重叠然后它变得越来越糟。内核执行时间约为6ms。在前两个流执行几乎完全并发后,其余的流之间的距离为3ms。关于5,我使用具有255寄存器文件的K20。所以我不希望那里有弊端。我真的不明白为什么我没有实现相当于gk110s指定的并发...

    请查看以下链接。有一个名为kF.png的图像。它显示了流的探查器输出.. !!!

    https://devtalk.nvidia.com/default/topic/531740/cuda-programming-and-performance/concurrent-streams-and-hyperq-for-k20/

2 个答案:

答案 0 :(得分:6)

内核之间的并发性取决于许多因素,但许多人忽略的只是内核的大小(即网格中的块数)。内核的大小可以自己有效地利用GPU通常不会在很大程度上同时运行,即使它们确实存在吞吐量优势。 GPU内部的工作分配器通常会在内核启动后立即开始分发块,因此如果一个内核在另一个内核之前启动,并且两者都有大量的块,那么第一个内核通常会占用GPU,直到它接近完成后,第二个内核的块将被调度和执行,可能会有少量的&#34;并发重叠&#34;。

重点是内核有足够的块来填充GPU&#34;将阻止其他内核实际执行,除了调度,这在计算3.5设备上没有任何不同。此外,不仅仅为内核指定一些参数作为一个整体,而且在块级别指定启动参数和统计信息(例如寄存器使用,共享内存使用等)有助于提供清晰的答案。计算3.5架构在这个领域的优势仍然主要来自&#34; small&#34; &#34;少数&#34;的内核块,试图一起执行。 Compute 3.5在那里有一些优势。

您还应该查看this question的答案。

  1. 当内核使用的全局内存未固定时,它会影响数据传输的速度,还会影响复制和计算的重叠能力,但不会影响两个内核并发执行的能力。然而,复制和计算重叠的限制可能会扭曲您的应用程序的行为。
  2. 不应该&#34;阅读冲突&#34;,我不确定你的意思。允许两个独立的线程/块/网格读取全局内存中的相同位置。通常,这将在L2缓存级别进行整理。只要我们谈论只是读取,就不会有冲突,也不会对并发产生特别的影响。
  3. 常量内存是一种有限的资源,在设备上执行的所有内核之间共享(尝试运行deviceQuery)。如果你还没有超过设备总数限制,那么唯一的问题就是利用常量缓存,以及缓存抖动等问题。除了这种二级关系外,对并发没有直接影响。
  4. 识别共享内存每块而不是每个内核的数量会更有启发性。这将直接影响可以在SM上安排的块数。但是,如果您指定了每个内核的启动配置以及启动调用的相对时间,那么回答这个问题也会更加清晰。 如果共享内存恰好是调度的限制因素,那么您可以将每个SM的总可用共享内存除以每个内核使用的数量,以便基于此了解可能的并发性。我个人认为,每个网格中的块数可能是一个更大的问题,除非你的内核每个网格使用10k,但整个网格只有几个块。
  5. 我在这里的评论与我对4的响应几乎相同。看看你的设备的deviceQuery,如果寄存器成为每个SM上调度块的限制因素,那么你可以通过每个内核的寄存器使用来划分每个SM的可用寄存器(再次,讨论每个块的寄存器使用情况和内核中的块数更有意义)来发现可能的限制。
  6. 同样,如果您有合理大小的内核(数百或数千个块或更多),那么工作分配器对块的调度很可能是内核之间并发量的主要因素。

    编辑:以回应问题中发布的新信息。我看过kF.png

    1. 首先让我们从每个SM的角度分析一下。 CC 3.5允许16&#34;打开&#34;或每个SM当前安排的块。如果你要发布每个61个块的2个内核,这可能足以填补&#34;准备好了#34;在CC 3.5设备上排队。换句话说,GPU一次可以处理其中的两个内核。作为其中一个内核&#34;排水管&#34;然后由工作经销商安排另一个内核。第一个内核的块&#34;排放&#34;足够大约一半的总时间​​,以便下一个内核在前两个内核完成的大约中途进行调度,因此在任何给定点(在时间轴上绘制一条垂直线),您可以同时执行2或3个内核。 (根据图表,启动的第3个内核与前2个内核重叠约50%,我不同意你的说法,即每次连续内核启动之间有3ms的距离)。如果我们说在峰值时我们有3个内核被调度(有很多垂直线将与3个内核时间线相交)并且每个内核有大约60个块,那么大约是180个块。你的K20有13个SM和each SM can have at most 16 blocks scheduled on it。这意味着在最高峰时你可以安排大约180个区块(可能),而理论峰值为16 * 13 = 208.所以你在这里非常接近最大值,并且你可能没有多少得到。但也许你认为你只有120/208,我不知道。
    2. 现在让我们从共享内存的角度来看一看。一个关键问题是您的L1 /共享分割的设置是什么?我相信每个SM默认为48KB的共享内存,但如果你改变了这个设置,那将非常重要。无论如何,根据您的声明,每个预定的块将使用10KB的共享内存。这意味着我们最多可以为每个SM调度大约4个块,或者4 * 13个总块=最多可以在任何给定时间调度的52个块。您显然超过了这个数字,所以我可能没有足够的信息来了解内核的共享内存使用情况。如果你真的使用10kb / block,这或多或少会阻止你一次执行多个内核的线程块。可能仍有一些重叠,我相信这可能是您申请中的实际限制因素。 60个块的第一个内核被安排。在几个块流失之后(或者可能因为两个内核一起足够靠近地启动),第二个内核开始进行调度,因此几乎同时进行。然后我们需要等待一段时间才能在第3个内核可以调度之前排出内核的块,这可能是时间轴中指示的50%点。
    3. 无论如何,我认为上面的分析1和2清楚地表明,基于内核结构中固有的限制,您可以从设备中获得大部分功能。 (我们可以根据寄存器进行类似的分析,以发现这是否是一个重要的限制因素。)关于这个声明:&#34;我真的不明白为什么我没有达到与gk110s指定的相同的并发...&# 34;我希望您看到并发规范(例如32个内核)是最大规范,并且在大多数情况下,在达到最大数量限制之前,您将遇到其他类型的机器限制可以同时执行的内核。

      关于文档和资源的

      编辑:,我从Greg Smith上面链接的答案提供了一些资源链接。以下是其他一些内容:

答案 1 :(得分:0)

到目前为止,我对HyperQ的经验是我的内核并行化的2-3(3.5)次,因为对于更复杂的计算,内核通常更大。对于小内核来说,它是一个不同的故事,但通常内核更复杂。

Nvidia在他们的cuda 5.0文档中也回答了这一问题,即更复杂的内核将减少并行化的数量。

但是,GK110仍然有很大的优势,只允许这样做。