【问题标题】:Parallel compute shaders execution in Vulkan?Vulkan 中的并行计算着色器执行?
【发布时间】:2018-11-28 08:36:29
【问题描述】:

我有几个计算着色器(我们称它们为compute1compute2 等等),它们有几个输入绑定(在着色器代码中定义为layout (...) readonly buffer)和几个输出绑定(定义为layout (...) writeonly buffer)。我正在将带有数据的缓冲区绑定到它们的描述符集,然后尝试并行执行这些着色器


我的尝试:

  1. vkQueueSubmit()VkSubmitInfo.pCommandBuffers 持有多个主命令缓冲区(每个计算着色器一个);
  2. vkQueueSubmit()VkSubmitInfo.pCommandBuffers 拥有一个使用 vkCmdExecuteCommands() 记录的主命令缓冲区,pCommandBuffers 拥有多个辅助命令缓冲区(每个计算着色器一个);
  3. vkQueueSubmit()+vkQueueWaitIdle() 与不同的std::thread 对象分开(每个计算着色器一个)- 每个命令缓冲区分配在单独的VkCommandPool 中,并提交给自己的VkQueue 和自己的VkFence,主线程正在等待使用threads[0].join(); threads[1].join(); 等等;
  4. vkQueueSubmit() 与不同的分离 std::thread 对象分开(每个计算着色器一个)- 每个命令缓冲区分配在单独的VkCommandPool 中,并提交给自己的VkQueue 和自己的@987654342 @,主线程正在等待使用 vkWaitForFences()pFences 持有在 vkQueueSubmit() 中使用的栅栏和 waitAll 持有 true

我有什么:

在所有情况下,结果时间几乎相同(差异小于 1%),就像为 compute1 调用 vkQueueSubmit()+vkQueueWaitIdle(),然后为 compute2 等等。

我想为多个着色器绑定相同的缓冲区作为输入,但根据时间,如果每个着色器都使用自己的VkBuffer+VkDeviceMemory 对象执行,结果是相同的。


所以我的问题是

是否有可能以某种方式同时执行多个计算着色器,或者命令缓冲区并行性仅适用于图形着色器?


更新:测试应用程序是使用 LunarG Vulkan SDK 1.1.73.0 编译的,并在带有 NVIDIA GeForce GTX 960 的 Windows 10 上运行。

【问题讨论】:

  • 是什么让您认为这些都没有并行执行着色器?同样重要的是……你为什么在乎?重要的是工作完成的速度,而不是它们是否“并行”执行,对吗?如果 GPU 有 20 个计算单元,并且每次调度需要 60 个计算单元,那么执行每个计算操作超过 10 个单元(用于并行执行)不会比执行超过 20 个单元快。
  • 你说得对:我真正想要的只是我能达到的最高性能。我以可以轻松并行完成的方式设计算法,因此我试图最大化利润。
  • 您是否尝试过使用一个命令缓冲区,其中包含背靠背调度?只要它们之间没有障碍/事件依赖关系,它们就会按顺序开始,但之后可以并行进行,例如如果第一次调度没有填满所有执行单元,那么第二次调度可以填补漏洞(如果硬件能够做到这一点)。我相信大多数硬件都可以支持这种级别的并行性,即使它们不支持多个独立队列——它允许它们在一个调度完成和下一个调度开始时保持高利用率。
  • @JesseHall,您能否提供一个想法或链接的示例?我不完全明白你的意思,而谷歌搜索“背靠背调度”没有帮助。
  • 我的意思是开始一个命令缓冲区,为compute1绑定描述符集,为compute1分派,为compute2绑定描述符集,为compute2分派,...,结束命令缓冲区。跨度>

标签: c++ parallel-processing glsl vulkan compute-shader


【解决方案1】:

这取决于您正在执行应用程序的硬件。硬件导出处理提交命令的队列。顾名思义,每个队列依次执行命令。因此,如果您将多个命令缓冲区提交到单个队列,它们将按提交顺序执行。在内部,GPU 可以尝试并行执行提交的命令的某些部分(例如可以同时处理图形管道的单独部分)。但一般来说,单队列是按顺序处理命令的,不管你是提交图形命令还是计算命令。

为了并行执行多个命令缓冲区,您需要将它们提交到单独的队列中。但是硬件必须支持多个队列——它必须有单独的物理队列才能同时处理它们。

但是,更重要的是 - 我读到一些图形硬件供应商通过图形驱动程序模拟多个队列。换句话说 - 它们在 Vulkan 中公开多个队列,但在内部它们由单个物理队列处理,我认为您的问题就是这种情况,您的实验结果将证实这一点(当然,我不能确定)。

【讨论】:

  • 看来您对多队列模拟是正确的。但是让我们等待其他答案 - 我仍然希望在我错过的数百万个 Vulkan 参数中的某个地方有一些魔力:)
  • @zedrian 例如,这里是关于模拟多个队列的信息:reddit.com/r/vulkan/comments/7ynlcl/… 这部分特别有趣:“没有一家供应商拥有超过 1 个硬件图形队列 AFAIK,只有多个计算队列。(例如 AMD 有这个,NVidia 在驱动程序中模拟它)。"
  • 是的,这很有趣。但是这些多个计算队列在哪里呢?正如我的实验所示,看起来只有一个计算队列。
  • @zedrian 根据vulkan.gpuinfo.org Nvidia 960 确实有 2 个队列族,16 个通用队列和 1 个传输队列。但较新的 GPU(如 1050)有 3 个队列族(另外还有 8 个计算队列)。
猜你喜欢
  • 2021-01-30
  • 1970-01-01
  • 1970-01-01
  • 2022-07-20
  • 1970-01-01
  • 2011-04-24
  • 2021-10-31
  • 2016-12-27
  • 2021-09-10
相关资源
最近更新 更多