繁体   English   中英

用于多个内核的Cuda流处理

[英]Cuda Stream Processing for multiple kernels Disambiguation

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

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

  1. dev_input和dev_output没有固定;
  2. dev_input大小与dev_input大小s * n的关系,其中每个内核读取唯一数据(无读取冲突)
  3. 内核从常量内存中读取数据
  4. 每个块分配10kb的共享内存。
  5. 内核使用60个寄存器

任何好的评论将不胜感激... !!!

干杯,塔纳西奥

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

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

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

内核之间的并发性取决于许多因素,但是许多人忽略的一个因素仅仅是内核的大小(即网格中的块数)。具有可以自行有效利用GPU的大小的内核通常不会在很大程度上并发运行,即使这样做,吞吐量优势也很小。 GPU内的工作分配器通常会在启动内核后立即开始分配块,因此,如果一个内核先于另一个内核启动,并且两个内核都有大量块,则第一个内核通常会占据GPU,直到将近完成后,第二内核的块将被调度并执行,可能会有少量“并发重叠”。

主要要点是,具有足够块以“填充GPU”的内核将阻止其他内核实际执行,并且除了调度之外,这在计算3.5设备上也没有任何不同。 此外,在块级别指定启动参数和统计信息(例如寄存器使用率,共享内存使用率等),不只是为整个内核指定几个参数,还有助于提供清晰的答案。 在此领域中,compute 3.5体系结构的优势仍将主要来自“少量”块的“小”内核,它们试图一起执行。 计算3.5在此具有一些优势。

您还应该查看该问题的答案。

  1. 如果不固定内核使用的全局内存,它将影响数据传输的速度,并影响复制和计算的重叠能力,但不会影响两个内核并发执行的能力。 但是,复制和计算重叠的限制可能会使应用程序的行为产生偏差。
  2. 不应有“读取冲突”,我不确定您的意思。 允许两个独立的线程/块/网格读取全局内存中的相同位置。 通常,这将在二级缓存级别得到解决。 只要我们谈论的只是阅读,就不应有冲突,并且对并发没有特殊影响。
  3. 恒定内存是有限的资源,在设备上执行的所有内核之间共享(尝试运行deviceQuery)。 如果您还没有超出设备总数限制,那么唯一的问题将是恒定高速缓存的利用率以及诸如高速缓存抖动之类的问题。 除了这种二级关系,对并发没有直接影响。
  4. 确定每个块而不是每个内核的共享内存量将更具指导意义。 这将直接影响一个SM可以调度多少个块。 但是,如果您指定了每个内核的启动配置以及启动调用的相对时间,那么回答这个问题也将变得更加清晰。 如果共享内存恰好是调度的限制因素,那么您可以将每个SM的可用共享内存总数除以每个内核使用的数量,以据此了解可能的并发性。 我个人的观点是,每个网格中的块数可能是一个更大的问题,除非您的内核每个网格使用10k,但整个网格中只有几个块。
  5. 我在这里的评论与我对4的回答几乎相同。看一下设备的deviceQuery, 如果寄存器成为每个SM上调度块的限制因素,那么您可以将每个SM的可用寄存器除以每个SM的寄存器使用量内核(同样,谈论每个块的寄存器使用情况和内核中的块数量更为有意义)以发现限制可能是多少。

同样,如果您具有合理大小的内核(数百个或数千个块或更多),则工作分配器对块的调度很可能将成为内核之间并发量的主要因素。

编辑:响应问题中发布的新信息。 我看了kF.png

  1. 首先,让我们从每个SM角度的块进行分析。 CC 3.5允许每个SM 16个“打开”或当前计划的块。 如果要启动2个每个61块的内核,这可能足以填补CC 3.5设备上的“准备就绪”队列。 换句话说,GPU可以一次处理其中两个内核。 当其中一个内核的块“填充”时,工作分配器将调度另一个内核。 第一个内核的块在总时间的一半左右就“耗尽”了足够的时间,因此,下一个内核的调度时间大约是前两个内核完成的一半,因此在任何给定的点(在时间轴上画一条垂直线)同时执行2个或3个内核。 (根据图表,第三个内核启动与前两个内核重叠约50%,我不同意您的说法,即每个连续的内核启动之间存在3ms的距离)。 如果说在高峰期我们调度了3个内核(有很多垂直线将与3个内核时间线相交),每个内核有〜60个块,那么大约是180个块。 您的K20有13个SM, 每个SM最多可以调度16个块 这意味着在高峰时(可能)有大约180个已调度的块,而理论峰值为16 * 13 =208。因此,您在此处非常接近max,并且没有更多的可能。 但也许您认为您只获得120/208,我不知道。
  2. 现在让我们从共享内存的角度来看一下。 一个关键问题是您的L1 /共享拆分的设置是什么? 我相信它默认为每个SM 48KB共享内存,但是如果您更改了此设置,那将非常重要。 无论如何,根据您的声明,每个计划的块将使用10KB的共享内存。 这意味着每个SM最多可以调度4个块,或者总共4 * 13个块=可以在任何给定时间调度的最大52个块。 您显然超出了这个数字,所以可能我没有足够的信息来了解您的内核共享内存的使用情况。 如果您确实使用10kb / block,那么或多或少会阻止您一次执行多个内核的线程块。 仍然可能存在一些重叠,我相信这很可能是您应用程序中的实际限制因素。 排定了60个块的第一个内核。 在消耗了几个块之后(或者可能是因为两个内核启动得足够近了),第二个内核开始被调度,因此几乎是同时调度的。 然后,我们必须等待一段时间才能耗尽内核的大量块,然后才能安排第三个内核,这很可能在时间轴上所示的50%处。

无论如何,我认为上面的分析1和2清楚地表明,基于内核结构固有的限制,您将从设备中获得了大部分功能。 (我们可以基于寄存器进行类似的分析,以发现这是否是一个重要的限制因素。)关于此声明:“我真的不明白为什么我没有实现与gk110s所指定的并发等效的原因。”我希望您能看到并发规范(例如32个内核)是最大规范,并且在大多数情况下,在达到可以同时执行的最大内核数量限制之前,您将遇到其他某种计算机限制。

编辑:关于文档和资源,我从格雷格·史密斯上面链接到的答案提供了一些资源链接。 这里还有一些:

  • C编程指南中有一个关于异步并发执行的部分。
  • NVIDIA网络研讨会页面上的NVIDIA Steve Rennich博士演示了GPU并发和流

到目前为止,我对HyperQ的经验是内核并行化的2-3(3.5)倍,因为对于一些更复杂的计算,内核通常更大。 对于小内核,情况则不同,但通常内核会更复杂。

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

但是,GK110仍然具有很大的优势。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM