如何在Vulkan中的多个计算队列之间执行并行计算着色器?

问题描述

更新:此问题已解决,您可以在此处找到更多详细信息:https://stackoverflow.com/a/64405505/1889253

一个similar question was asked previously,但最初的问题集中在使用多个命令缓冲区,并在不同线程之间触发提交以实现着色器的并行执行。大多数答案表明解决方案是改为使用多个队列。在多个博客帖子和Khronos论坛答案中,使用多个队列似乎也是共识。我尝试了那些建议在多个队列中运行着色器执行的建议,但无法看到并行执行,因此我想问一下我可能做错了什么。如建议的那样,该问题包括将多个计算着色器的可运行代码提交给多个队列,希望对希望这样做的其他人(一旦解决)有用。

当前的实现是in this pull request / branch,但是我将介绍Vulkan的主要要点,以确保只需要Vulkan知识即可回答此问题。还值得一提的是,当前用例专用于计算队列和计算着色器,而不是图形或传输队列(尽管获得洞察/经验的经验仍然非常有用,并且很可能会得出答案)。

更具体地说,我有以下内容

在以上示例中不可见但很重要的几点:

  • 所有evalAsync在相同的应用程序,实例和设备上运行
  • 每个evalAsync都使用其自己的单独的commandBuffer和缓冲区,并在单独的队列中执行
  • 如果您想知道是否可能需要做一些内存障碍,我们尝试通过完全删除所有memoryBarriers(在着色器执行之前运行的this on for example)来解决问题,但这对性能没有任何影响

基准测试can be found here中使用的测试,但是唯一需要了解的关键是:

在运行测试时,我们首先在同一队列上运行一组“同步”着色器执行(数量是可变的,但我们已经使用6-16进行了测试,后者是最大队列数)。然后,我们以异步方式运行它们,在其中运行所有它们和evalAwait,直到它们完成为止。比较两种方法的结果时间时,即使它们跨不同的计算队列运行,它们也花费相同的时间。

我的问题是:

  • 获取队列时我当前是否缺少某些东西?
  • vulkan设置中是否还需要配置其他参数以确保异步执行?
  • 对于仅能够以同步方式向GPU提交GPU工作负载的潜在操作系统进程,我是否可能没有任何限制?
  • 在处理多个队列提交时,是否需要多线程才能使并行执行正常工作?

此外,我还在各种reddit帖子和Khronos Group论坛上找到了一些有用的资源,这些资源提供了关于该主题的非常深入的概念和理论概述,但是我还没有遇到能够并行执行的端到端代码示例着色器。如果您可以分享一些实用的示例,并且可以并行执行着色器,那将非常有帮助。

如果还有其他细节或问题可以帮助您提供更多的背景信息,请告诉我,我们很乐意回答和/或提供更多细节。

出于完整性考虑,我的测试使用的是:

  • Vulkan SDK 1.2
  • Windows 10
  • NVIDIA 1650

在类似帖子中分享的其他相关链接

解决方法

您将获得“异步执行”。您只是不希望它的行为方式如此。

在CPU上,如果有一个活动线程,则说明您正在使用一个CPU内核(或超线程)。所有该内核的执行和计算功能都单独分配给您的线程(忽略抢占)。但是同时,如果有其他核心,则您的一个线程无法使用这些核心的任何计算资源。除非您创建另一个线程,否则不会。

GPU不能那样工作。队列不是像CPU线程。它并不具体涉及特定数量的计算资源。队列只是执行命令的接口;底层的硬件决定了如何将命令分配给GPU整体提供的各种计算资源。

执行命令时通常会发生的情况是,硬件会尝试使用命令完全饱和可用的着色器执行单元。如果可用的着色器单元数超过操作所需的调用次数,则某些资源可立即用于下一个命令。但是,如果没有,那么整个GPU的计算资源将专用于执行第一个操作。第二个必须等待资源可用才能开始。

您应该将多少计算队列投入工作;他们都将尝试使用尽可能多的计算资源。因此它们将在很大程度上按特定顺序执行。

存在队列优先级系统,但是这些系统主要有助于确定命令的执行顺序。也就是说,如果高优先级队列中有一些需要执行的命令,那么下次计算资源可用于新命令时,它们将具有优先级。

因此,在3个单独的队列中提交3个调度批处理不会比在一个包含3个调度操作的队列中提交1个批处理快。

存在多个(相同系列的)队列的主要原因是能够从多个线程提交工作,而无需进行线程间同步(并提供一些可能的提交优先级)。

,

我已经能够使用this suggestion解决问题。为了提供进一步的上下文,我试图将命令提交到同一系列中的多个队列,但是在链接的建议中指出,NVIDIA(和其他GPU供应商)在并行处理命令时具有不同的功能范围。提交。

在我的特定情况下,我正在测试的NVIDIA 1650卡仅在将工作负载提交到不同队列系列时才支持并发处理-更具体地说,它仅支持在一个图形队列和一个计算系列中进行一次并发命令提交。队列。

我重新实现了代码,以允许为特定命令分配族队列,并且我能够实现并行处理(通过在两个queueFamilies中提交,速度提高了2倍)。

有关实现https://kompute.cc/overview/async-parallel.html

的更多详细信息