【发布时间】:2018-11-28 08:36:29
【问题描述】:
我有几个计算着色器(我们称它们为compute1、compute2 等等),它们有几个输入绑定(在着色器代码中定义为layout (...) readonly buffer)和几个输出绑定(定义为layout (...) writeonly buffer)。我正在将带有数据的缓冲区绑定到它们的描述符集,然后尝试并行执行这些着色器。
我的尝试:
-
vkQueueSubmit()和VkSubmitInfo.pCommandBuffers持有多个主命令缓冲区(每个计算着色器一个); -
vkQueueSubmit()和VkSubmitInfo.pCommandBuffers拥有一个使用vkCmdExecuteCommands()记录的主命令缓冲区,pCommandBuffers拥有多个辅助命令缓冲区(每个计算着色器一个); - 将
vkQueueSubmit()+vkQueueWaitIdle()与不同的std::thread对象分开(每个计算着色器一个)- 每个命令缓冲区分配在单独的VkCommandPool中,并提交给自己的VkQueue和自己的VkFence,主线程正在等待使用threads[0].join(); threads[1].join();等等; - 将
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