如何使用Nsight读取CUDA动态并行性的分析结果

4
我目前正在使用CUDA 5.0中引入的新的CUDA动态并行性(CDP)功能进行尝试。我选择N-queens puzzle作为树搜索算法的例子,这种算法具有高工作不平衡性,我认为CDP可能会从中受益。
我的方法大致如下:对于给定的棋盘配置(一个带有一定数量皇后已经放置在第一行的棋盘),我启动了一个带有多个线程的内核。每个线程尝试下面给定最大深度的子树中的一个可能分支。如果分支的叶子仍然表示一个有效的配置,则该线程会生成一个子网格线程,用于搜索基于该配置的子树。找到其配置无效(两个或更多个皇后可以互相攻击)的线程将终止。如果线程成功地将最后一个皇后放在了棋盘上,则它将增加解决方案计数器。
在启动内核之前,我在CPU上预先计算了一些棋盘配置,然后为每个配置启动了一个网格。
现在问题来了:我发现我的解决方案比另一个不使用CDP的CUDA实现要慢得多。因此,我启动了Nsisght分析器以找出原因。以下是我的第一个结果(当N=10时):

Nsight profiling result for N=10 without streams.

显然GPU没有完全占用。因此,我认为我需要使用不同的流来启动子网格,以防止它们相互等待。下面是使用每个子网格启动新流时的分析结果:

enter image description here

这看起来更加密集(并且速度更快),但我仍然不太理解这种模式的原因。为什么有些启动之间会有这么多的间隙(尤其是在结尾处)?
但情况变得更加奇怪了。当我将 N(因此工作量)增加到 13 时,模式如下所示:

enter image description here

有人知道CDP的内部工作原理吗?我是否没有考虑到任何隐式同步屏障?或者我是否错误地阅读了分析器输出?我特别想知道在最后一种情况下几乎涵盖整个执行时间的这个线程可能是什么。

我还没有找到关于Nsight Visual Profiler有关CDP输出的文档。任何关于Nsight所显示内容的好参考资料也会有所帮助。

谢谢!


关于文档,您可以在Profiler指南的1.5节中找到一些信息。 - Vitality
是的,我之前也发现了。不幸的是,该指南没有提到“计算”行中不同小条的含义,特别是垂直轴上所表示的内容。该指南仅提供了没有CDP的示例,只显示此行中的单个条形图。但无论如何,还是谢谢! - Frank Rupprecht
我不确定,但我猜测对于动态并行性来说,有两个时间轴,即水平的经典时间轴和一个垂直的时间轴,用于指示子内核的持续时间。 - Vitality
你是怎么看到所有的流都分开的?当我对使用CDP的代码进行分析时,我只能看到默认流。子内核出现为空流,即使我为每个内核创建了非阻塞流。 - Cristobal Navarro
1个回答

6
我可以回答您的分析器问题。我将参考您问题中的最后一张图片。
“计算”行显示上下文中发生的所有内核执行的摘要(在您的情况下,您似乎只有一个上下文在设备上,因此计算行因此显示设备上的所有活动)。
“计算”行内的子行用于显示并发内核执行(请注意,这适用于CDP和非CDP应用程序)。这些子行根据需要动态创建,取决于并发性如何。内核在某些子行中的放置不表示任何东西...它们只是使用试图最小化所需子行数量的启发式方法打包在一起。子行的高度也会缩放以使垂直空间合理。在您的情况下,您在某些点上具有很多并发性,因此看起来您有30多个子行,这意味着在某些点上您有30多个内核同时在设备上执行。
计算行的目标是概述GPU随时间的繁忙程度。要查看正在执行的特定内核,您需要在时间轴中探索内核行。
内核时间轴显示在上下文时间轴的正下方。每个主机启动的内核都有一行。与计算行一样,如果需要显示该内核的并发执行,则内核行可以具有子行。对于CDP应用程序,内核行还可以具有表示从该内核启动的内核的子内核行。
对于您的示例,我看到一个单独的主机启动的内核“nQue...”。请注意,此内核有7个子行,因为在某些点上有7个内核实例同时执行。对于不启动子内核的内核,内核执行由实心间隔表示,显示该内核实例在GPU上执行的时间。对于启动子内核的内核,内核执行还可以包括末尾的空洞部分。空洞部分表示内核完成执行后等待子内核完成执行的时间。CDP执行模型要求父内核在所有子内核完成之前不得完成,这就是空洞部分所显示的。
您可以通过展开父内核时间轴来查看确切的父/子关系。请注意,“nQue...”时间轴行旁边的“+”图标。如果打开它,您将看到时间轴行中的任何“nQue...”内核启动的所有子内核。那些子内核又可以展开,如果它们启动了自己的子内核。
如果您想查看特定内核的“家谱”,有两种方法可以做到这一点。您可以选择一个内核,所有祖先和后代都会在内核行和计算行中突出显示。您可以在您的图片中看到这一点。Ctrl-select也可以多选。如果选择单个内核并右键单击,则可以在菜单中选择“聚焦”,这将隐藏除该内核的祖先/后代之外的所有内核。从同一菜单中使用“不聚焦”来恢复所有内核。

针对您关于长时间执行的内核的具体问题。它似乎是从主机启动的“nQue…”实例之一。如果不了解代码,我无法说出为什么它执行时间如此之长。您可以选择它并使用“聚焦”功能查看它所启动的子内核,也许这会提供一些见解。


谢谢你提供如此全面的答案!这是非常宝贵的信息。我希望Nvidia能够将其包含在文档中。我会根据你给我的提示来调查那个长时间的内核执行的原因。再次感谢! - Frank Rupprecht
我们已经在更新文档以包含此信息的过程中了。 - deadeye

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接