首页 > 解决方案 > Vulkan 中的并行计算着色器执行?

问题描述

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


我试过的:

  1. vkQueueSubmit()拥有VkSubmitInfo.pCommandBuffers多个主要命令缓冲区(每个计算着色器一个);
  2. vkQueueSubmit()VkSubmitInfo.pCommandBuffers保存一个主命令缓冲区,该缓冲区是使用保存vkCmdExecuteCommands()多个pCommandBuffers辅助命令缓冲区(每个计算着色器一个)记录的;
  3. vkQueueSubmit()将+vkQueueWaitIdle()从不同的对象中分离出来std::thread(每个计算着色器一个) - 每个命令缓冲区是单独分配的,VkCommandPool并且正在使用 own 提交给自己VkQueueVkFence主线程正在等待使用threads[0].join(); threads[1].join();,依此类推;
  4. vkQueueSubmit()与不同的分离 对象分开std::thread(每个计算着色器一个) - 每个命令缓冲区是单独分配的,VkCommandPool并且正在使用 own 提交给 own VkQueueVkFence主线程正在等待使用vkWaitForFences()与hold 一起使用的pFences栅栏,该栅栏在中使用vkQueueSubmit()和与waitAllholding一起使用true

我有什么:

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

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


所以我的问题是

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


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

标签: c++parallel-processingglslvulkancompute-shader

解决方案


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

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

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


推荐阅读