在我的机器上,我有两个队列系列,一个支持所有内容,另一个支持转移。
支持所有内容的队列系列的queueCount为16
。
现在规范陈述
提交到不同队列的命令缓冲区可以并行执行,甚至可以相对于彼此无序执行
这是否意味着我应该尝试使用所有可用的队列来获得最佳性能?
答案 0 :(得分:14)
到底是什么?
采用延迟渲染器的典型结构。你可以构建你的g-buffers,做你的光照通道,做一些后期处理和色调映射,也可以投入一些透明的东西,然后呈现最终的图像。每个过程都取决于之前已完成的过程,然后才能开始。在您完成g-buffer之前,您无法完成光照通道。等等。
如何在多个执行队列中并行化?您无法并行化g-buffer构建或光照通道,因为所有这些命令都写入相同的附加图像(并且您无法从多个队列中执行此操作)。如果他们没有写入相同的图像,那么您将不得不选择一个队列,将结果图像合并到最终图像中。另外,我不知道如果不使用相同的深度缓冲区,深度缓冲将如何工作。
这个组合步骤需要同步。
现在,有许多可以并行化的任务。做截头剔除。粒子系统更新。记忆转移。像这样的东西;用于 next 框架的数据。但是你有多少队列可以实际上保持忙碌? 3?也许4?
更不用说,您需要构建可扩展的渲染系统。 Vulkan不要求实现提供多于1个队列。因此,您的代码需要能够在仅提供一个队列的系统以及提供16的系统上合理运行。并且要利用16队列系统,您可能需要以非常不同的方式呈现。
哦,请注意,如果您要求排队,但不要使用它们,的性能可能会受到影响。如果您要求8个队列,则实现别无选择,只能假设您打算能够发出8个并发命令集。这意味着硬件无法将其所有资源专用于单个队列。因此,如果您只使用其中的3个......您可能会将超过50%的潜在性能损失到实施等待您使用的资源。
当然,实现可以动态扩展这些事情。但除非你描述这个特例,否则你永远不会知道。哦,如果它确实动态扩展...那么你就不会因为使用这样的多个队列而获得。
答案 1 :(得分:14)
是的,如果您拥有高度独立的工作负载,请使用单独的队列。
如果队列之间需要大量同步,则可能会扼杀您可能获得的任何潜在好处。
基本上你正在做的是为GPU提供它可以做的一些替代工作(并且在同一队列系列的情况下填充档位和气泡和空闲并给予GPU选择)。并且有一些潜力可以更好地使用CPU(例如,单线程与每个线程一个队列)。
使用单独的传输队列(或其他专业系列)似乎是推荐的方法。
一般而言。 SW和NB的答案已经提出了更现实,经验,怀疑和实践的观点。实际上,由于这些队列针对相同的资源,具有相同的限制和其他常见限制,因此必须更加谨慎,这限制了从中获得的潜在好处。值得注意的是,如果驱动程序使用多个队列做错了,那么缓存可能非常糟糕。
这个AMD的Leveraging asynchronous queues for concurrent execution(2016)讨论了它如何映射到他们的HW \驱动程序。它显示了使用单独队列系列的潜在好处。它表示尽管他们提供了两个计算系列队列,但他们当时并没有观察到应用程序的优势。他们说他们只有一个图形队列,为什么。
NVIDIA似乎也有类似“异步计算”的想法。显示在Moving to Vulkan: Asynchronous compute。
为了安全起见,我们似乎仍然应该只使用一个图形和一个异步计算队列,尽管在当前的硬件上。 16个队列似乎是一个陷阱和伤害自己的方式。
使用传输队列并不像看起来那么简单。您应该使用专用的主机 - >设备传输。非专用应该用于设备 - >设备转移操作。
答案 2 :(得分:8)
这很大程度上取决于您的实际场景和设置。没有任何细节,很难说清楚。
如果您向多个队列提交命令缓冲区,您还需要进行适当的同步,如果这样做不正确,您可能会获得比仅使用一个队列更差的性能。
请注意,即使您只提交到一个队列,实现也可以并行执行命令缓冲,甚至无序执行(也就是"在飞行中"),请参阅第{{C}章节中的详细信息。 3}}或chapter 2.2 of the specs。
如果使用计算和图形,使用单独的队列同时提交(和同步)将提高支持异步计算的硬件的性能。
因此,如果不知道您的实际用例,就没有明确的肯定或否定。
答案 3 :(得分:0)
由于您可以在同一个队列中提交多个独立的工作负载,而且它们之间似乎没有任何隐式的排序保证,因此,您实际上并不需要多个队列来使队列系列达到饱和。因此,我想多个队列的唯一目的是允许队列之间的不同优先级,如设备创建期间所指定的。
我知道此答案与公认的答案直接矛盾,但是该答案无法解决您不需要更多队列即可向设备发送更多并行工作的问题。