25

在我的机器上,我有两个队列族,一个支持一切,一个只支持传输。

支持一切的队列族的 queueCount 为16.

现在规格说明

提交到不同队列的命令缓冲区可能会并行执行,甚至可能彼此乱序执行

这是否意味着我应该尝试使用所有可用队列以获得最大性能?

4

4 回答 4

23

是的,如果您有高度独立的工作负载,请使用单独的队列。

如果队列之间需要大量同步,则可能会扼杀您可能获得的任何潜在好处。

基本上,您正在做的是在相同队列系列的情况下为 GPU 提供它可以做的一些替代工作(并填充停顿、气泡和空闲,并为 GPU 提供选择)。并且有一些更好地使用 CPU 的潜力(例如,单线程与每个线程一个队列)。

使用单独的传输队列(或其他专门的系列)似乎甚至是推荐的方法。

一般而言就是这样。SW 和 NB 的答案已经提出了更现实、经验、怀疑和实际的观点。实际上,人们必须更加谨慎,因为这些队列针对相同的资源、具有相同的限制和其他常见限制,从而限制了从中获得的潜在利益。值得注意的是,如果驱动程序对多个队列做了错误的事情,那么缓存可能非常非常糟糕。

AMD 的Leveraging asynchronous queues for concurrent execution (2016) 讨论了它如何映射到他们的硬件\驱动程序。它显示了使用单独队列族的潜在好处。它说,尽管他们提供了两个计算系列队列,但他们当时并没有观察到应用程序的好处。他们说他们只有一个图形队列,为什么。

NVIDIA 似乎对“异步计算”也有类似的想法。如迁移到 Vulkan:异步计算中所示。

为了安全起见,尽管在当前硬件上,我们似乎仍然应该只使用一个图形和一个异步计算队列。16个队列似乎是一个陷阱,也是一种伤害自己的方式。

对于传输队列,它也不像看起来那么简单。您应该使用专用的主机->设备传输。并且非专用应该用于设备->设备传输操作。

于 2016-06-01T20:13:55.933 回答
18

达到什么目的?

以延迟渲染器的典型结构为例。你建立你的g-buffers,做你的光照通道,做一些后期处理和色调映射,可能会加入一些透明的东西,然后呈现最终的图像。每个过程都依赖于在开始之前已经完成的前一个过程。在完成 g-buffer 之前,您无法进行光照传递。等等。

你怎么能在多个执行队列中并行化呢?您无法并行化 g-buffer 构建或照明通道,因为所有这些命令都写入相同的附加图像(并且您不能从多个队列中执行此操作)。如果他们没有写入相同的图像,那么您将不得不选择一个队列,将生成的图像组合成最终的图像。此外,我不知道如果不使用相同的深度缓冲区,深度缓冲将如何工作。

并且该组合步骤将需要同步。

现在,有许多任务可以并行化。进行截锥剔除。粒子系统更新。内存传输。像这样的东西; 用于下一帧的数据。但是,您实际上可以同时保持多少队列忙碌?3? 也许4?

更不用说,您将需要构建一个可以扩展的渲染系统。Vulkan 不要求实现提供超过 1 个队列。因此,您的代码需要能够在仅提供一个队列的系统以及提供 16 个队列的系统上合理运行。为了利用 16 个队列系统,您可能需要以非常不同的方式进行渲染。

哦,请注意,如果您要求一堆队列,但不使用它们,性能可能会受到影响。如果您要求 8 个队列,则实现别无选择,只能假设您打算能够发出 8 个并发命令集。这意味着硬件不能将其所有资源都专用于单个队列。因此,如果您只使用其中的 3 个......您可能会失去超过 50% 的潜在性能,而这些资源正在等待您使用的实现。

当然,实现可以动态地扩展这些东西。但除非你对这个特殊情况进行分析,否则你永远不会知道。哦,如果它确实是动态扩展的......那么你也不会从使用这样的多个队列中获得很多。

最后,已经有一些关于在多个平台上多队列提交如何有效地保持 GPU 供电的研究(阅读所有部分)。它的总长短似乎是:

  1. 让多个队列执行真正的渲染操作并没有帮助。
  2. 拥有一个带有一个或多个计算队列(作为实际计算队列或您提交计算工作的图形队列)的单个渲染队列对于在渲染操作期间保持执行单元充分饱和很有用。
于 2016-06-01T17:34:26.393 回答
9

这在很大程度上取决于您的实际场景和设置。没有任何细节很难说。

如果您将命令缓冲区提交到多个队列,您还需要进行适当的同步,如果没有正确完成,您实际上可能会获得比仅使用一个队列更差的性能。

请注意,即使您只提交一个队列,实现也可能并行执行命令缓冲区,甚至是无序执行(也称为“运行中”),请参阅规范的第 2.2 章此 AMD 演示文稿中的详细信息。

如果您进行计算和图形处理,使用同时提交(和同步)的单独队列将提高支持异步计算的硬件的性能。

因此,在不了解您的实际用例的情况下,对此没有明确的“是”或“否”。

于 2016-06-01T17:27:07.003 回答
1

由于您可以在同一个队列中提交多个独立的工作负载,而且它们之间似乎没有任何隐含的顺序保证,因此您实际上并不需要多个队列来使队列族饱和。所以我猜多个队列的唯一目的是允许队列之间的不同优先级,如设备创建期间指定的那样。

我知道这个答案与接受的答案直接矛盾,但该答案无法解决您不需要更多队列来向设备发送更多并行工作的问题。

于 2018-07-17T21:36:41.990 回答