我目前正在使用CUDA 5.0中引入的新CUDA动态并行(CDP)功能。 我选择N-queens puzzle作为具有高工作不平衡的树搜索算法的示例,在我看来,这可能会受益于CDP。
我的方法大致如下:对于给定的板配置(在第一行中已经放置了一定数量的皇后的棋盘),我启动了一个具有多个线程的内核。每个线程在给定配置下尝试子树的一个可能分支,直到给定的最大值。深度。如果分支的保留仍然表示有效配置,则该线程生成一个子网格线程,该子网格搜索子树,然后基于该配置。发现其配置无效(两个或多个皇后可能互相攻击)的线程将终止。如果一个线程成功地将最后一个皇后放置在板上,它会递增解决方案计数器。
在启动内核之前,我预先计算CPU上的一些电路板配置,然后为每个配置启动网格。
现在问题:我发现我的解决方案明显慢于另一个不使用CDP的CUDA实现。所以我启动了Nsight剖析器来找到原因。这是我的第一个结果(对于N = 10):
显然GPU没有完全占用。所以我想我需要使用不同的流来启动子网格,以防止它们相互等待。以下是为每个子网格启动使用新流时的分析结果:
这看起来更密集(并且更快),但我仍然不太明白这种模式的原因。为什么在一些发布之间会有这么多的噱头(特别是最后)?
但它变得更加奇怪。当我将N(以及工作负载)增加到13时,模式如下所示:
有人知道CDP如何在内部运作吗?我还没有考虑任何隐含的同步障碍吗?或者我在读取分析器输出错误?我特别好奇在最后一种情况下几乎整个执行时间内的这一个线程是什么。
我也没有找到有关CDP输出的Nsight Visual Profiler的任何文档。关于Nsight在那里展示什么的任何好的参考也会有所帮助。
谢谢!
答案 0 :(得分:6)
我可以回答你的探查者问题。我将参考你问题中的最后一张图片。
“Compute”行显示上下文中发生的所有内核执行的摘要(在您的情况下,您似乎在设备上只有一个上下文,因此计算行显示设备上的所有活动)。
Compute行中的子行用于显示并发内核执行(请注意,对于CDP和非CDP应用程序都是如此)。这些子行是根据需要动态创建的,具体取决于并发性。内核在某些子行中的放置并不表示任何内容......它们只是使用试图最小化所需子行数的启发式打包。子行的高度也被缩放以保持垂直空间合理。在你的情况下,你在某些点上有很多并发性,所以看起来你有30多个子行,这意味着你可以在设备上同时执行30多个内核。
Compute行的目标是概述GPU随时间的繁忙程度。要具体了解正在执行的内核,您需要在时间轴中探索内核行。
内核时间轴显示在上下文时间轴的下方。每个主机启动的内核都有一行。与Compute行一样,如果需要显示内核的并发执行,内核行可以有子行。对于CDP应用程序,内核行也可以有子内核行,代表从该内核启动的内核。
对于您的示例,我看到一个主机启动的内核“nQue ...”。请注意,此内核有7个子行,因为在某些点上有7个内核实例同时执行。对于不启动子内核的内核,内核执行由实体间隔表示,显示内核实例在GPU上执行的时间。对于启动子内核的内核,内核执行也可以在末尾包含空心部分。空心部分表示内核完成执行后等待子内核完成执行的时间。 CDP执行模型要求父内核在所有子内核完成之前不会完成,这就是空心部分显示的内容。
您可以通过展开父内核时间轴来查看确切的父/子关系。注意“nQue ...”时间轴行旁边的“+”图标。如果打开,您将看到时间轴行中任何“nQue ...”内核启动的所有子内核。如果这些子内核启动了自己的孩子,那么这些子内核又可以扩展。
如果要查看特定内核的“族树”,有两种方法可以执行此操作。您可以选择内核,所有祖先和后代将在内核行和计算行中突出显示。您可以在图像中看到这一点。 Ctrl-select也适用于多选。如果选择单个内核并右键单击,则可以在菜单中选择“Focus”,这将隐藏除该内核的祖先/后代之外的所有内核。使用同一菜单中的“不要聚焦”来恢复所有内核。
关于长期执行内核的具体问题。它似乎是从主机发起的“nQue ......”实例之一。我不知道为什么它在执行这么长时间而不了解更多代码。您可以选择它并使用Focus功能来确切地查看它正在启动的子内核,这可能会提供一些见解。