在 Vulkan 中执行并行计算着色器?

Parallel compute shaders execution in Vulkan?

本文关键字:并行计算 Vulkan 执行      更新时间:2023-10-16

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


我尝试过:

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

我得到了什么:

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

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


所以我的问题是

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


更新:測試應用程式使用 LunarG Vulkan SDK 1.1.73.0 編譯,並在 Windows 10 上運行 NVIDIA GeForce GTX 960。

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

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

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