我应该尝试使用尽可能多的队列吗?
Should I try to use as many queues as possible?
在我的机器上我有两个队列系列,一个支持一切,一个只支持传输。
支持一切的队列系列的queueCount为16
。
现在规格说明
Command buffers submitted to different queues may execute in parallel or even out of order with respect to one another
这是否意味着我应该尝试使用所有可用队列以获得最佳性能?
这在很大程度上取决于您的实际场景和设置。没有细节很难说。
如果您将命令缓冲区提交给多个队列,您还需要进行适当的同步,如果做得不对,您实际上可能会获得比仅使用一个队列更差的性能。
请注意,即使您只提交到一个队列,实现也可能会并行执行命令缓冲区,甚至乱序执行(又名 "in-flight"),请参阅第 chapter 2.2 of the specs or this AMD presentation 章中的详细信息.
如果您进行计算和图形处理,使用同时提交(和同步)的单独队列将提高支持异步计算的硬件的性能。
因此,在不了解您的实际用例的情况下,没有明确的是或否。
目的是什么?
采用延迟渲染器的典型结构。你建立你的 g 缓冲区,做你的照明通道,做一些 post 处理和色调映射,也许扔一些透明的东西,然后呈现最终图像。每个过程都取决于前一个过程在开始之前已经完成。在你完成你的 g-buffer 之前你不能做你的光照过程。等等。
如何跨多个执行队列并行执行?你不能并行构建 g-buffer 或光照通道,因为所有这些命令都写入相同的附加图像(并且你不能从多个队列执行此操作)。如果他们没有写入相同的图像,那么您将不得不选择一个队列来将生成的图像组合成最终图像。另外,我不知道如果不使用相同的深度缓冲区,深度缓冲将如何工作。
并且该组合步骤需要同步。
现在,有很多任务可以并行化。进行视锥体剔除。粒子系统更新。内存传输。像这样的东西;用于 next 帧的数据。但是,您实际上可以让多少队列同时保持忙碌? 3?也许 4?
更不用说,您将需要构建一个可以扩展的渲染系统。 Vulkan 不要求实现提供超过 1 个队列。因此,您的代码需要能够 运行 在仅提供一个队列的系统和提供 16 个队列的系统上合理地运行。要利用 16 队列系统,您可能需要以非常不同的方式呈现。
哦,请注意,如果您请求一堆队列,但不使用它们, 性能可能会受到影响。如果您要求 8 个队列,则实现别无选择,只能假设您打算能够发出 8 个并发命令集。这意味着硬件无法将其所有资源专用于单个队列。因此,如果您只使用其中的 3 个...您可能会将超过 50% 的潜在性能损失给实施等待您使用的资源。
诚然,实施可以动态地扩展这些东西。但除非你描述这个特殊案例,否则你永远不会知道。哦,如果它确实动态扩展...那么您也不会 从使用这样的多个队列中获得 很多。
- 让多个队列执行真正的渲染操作没有帮助。
- 拥有一个具有一个或多个计算队列(作为实际计算队列或您提交计算工作的图形队列)的单个渲染队列有助于在渲染操作期间保持执行单元充分饱和。
是的,如果您有高度独立的工作负载,请使用单独的队列。
如果队列之间需要大量同步,它可能会扼杀您可能获得的任何潜在好处。
基本上,在相同队列系列的情况下,您正在做的是为 GPU 提供它可以做的一些替代工作(并填充停顿、气泡和空闲,并为 GPU 提供选择)。并且有更好地使用 CPU 的潜力(例如,单线程与每个线程一个队列)。
使用单独的传输队列(或其他专门的系列)似乎甚至是推荐的方法。
一般来说。 SW 和 NB 的答案已经提出了更现实的、经验的、怀疑的和实用的观点。实际上,人们确实必须更加谨慎,因为这些队列以相同的资源为目标,具有相同的限制和其他常见限制,从而限制了由此获得的潜在好处。值得注意的是,如果驱动程序对多个队列做了错误的事情,它可能对缓存非常不利。
这个 AMD 的 Leveraging asynchronous queues for concurrent execution(2016) 讨论了它如何映射到他们的 HW\driver。它显示了使用单独队列系列的潜在好处。它说虽然他们提供了两个计算系列队列,但他们当时并没有观察到应用程序的好处。他们说他们只有一个图形队列,为什么。
NVIDIA好像也有类似的想法"asynch compute"。显示在 Moving to Vulkan: Asynchronous compute.
为了安全起见,尽管在当前硬件上,我们似乎仍应坚持只使用一种图形和一种异步计算队列。 16个队列似乎是一个陷阱和一种伤害自己的方式。
对于传输队列,它也不像看起来那么简单。您应该使用专用的主机-> 设备传输。而非专用应该用于设备->设备传输操作。
由于您可以在同一个队列中提交多个独立的工作负载,并且它们之间似乎没有任何隐式排序保证,因此您实际上不需要一个以上的队列来使队列族饱和。所以我猜多个队列的唯一目的是允许队列之间有不同的优先级,正如在设备创建期间指定的那样。
我知道这个答案与公认的答案直接矛盾,但那个答案未能解决您不需要更多队列来向设备发送更多并行工作的问题。
在我的机器上我有两个队列系列,一个支持一切,一个只支持传输。
支持一切的队列系列的queueCount为16
。
现在规格说明
Command buffers submitted to different queues may execute in parallel or even out of order with respect to one another
这是否意味着我应该尝试使用所有可用队列以获得最佳性能?
这在很大程度上取决于您的实际场景和设置。没有细节很难说。
如果您将命令缓冲区提交给多个队列,您还需要进行适当的同步,如果做得不对,您实际上可能会获得比仅使用一个队列更差的性能。
请注意,即使您只提交到一个队列,实现也可能会并行执行命令缓冲区,甚至乱序执行(又名 "in-flight"),请参阅第 chapter 2.2 of the specs or this AMD presentation 章中的详细信息.
如果您进行计算和图形处理,使用同时提交(和同步)的单独队列将提高支持异步计算的硬件的性能。
因此,在不了解您的实际用例的情况下,没有明确的是或否。
目的是什么?
采用延迟渲染器的典型结构。你建立你的 g 缓冲区,做你的照明通道,做一些 post 处理和色调映射,也许扔一些透明的东西,然后呈现最终图像。每个过程都取决于前一个过程在开始之前已经完成。在你完成你的 g-buffer 之前你不能做你的光照过程。等等。
如何跨多个执行队列并行执行?你不能并行构建 g-buffer 或光照通道,因为所有这些命令都写入相同的附加图像(并且你不能从多个队列执行此操作)。如果他们没有写入相同的图像,那么您将不得不选择一个队列来将生成的图像组合成最终图像。另外,我不知道如果不使用相同的深度缓冲区,深度缓冲将如何工作。
并且该组合步骤需要同步。
现在,有很多任务可以并行化。进行视锥体剔除。粒子系统更新。内存传输。像这样的东西;用于 next 帧的数据。但是,您实际上可以让多少队列同时保持忙碌? 3?也许 4?
更不用说,您将需要构建一个可以扩展的渲染系统。 Vulkan 不要求实现提供超过 1 个队列。因此,您的代码需要能够 运行 在仅提供一个队列的系统和提供 16 个队列的系统上合理地运行。要利用 16 队列系统,您可能需要以非常不同的方式呈现。
哦,请注意,如果您请求一堆队列,但不使用它们, 性能可能会受到影响。如果您要求 8 个队列,则实现别无选择,只能假设您打算能够发出 8 个并发命令集。这意味着硬件无法将其所有资源专用于单个队列。因此,如果您只使用其中的 3 个...您可能会将超过 50% 的潜在性能损失给实施等待您使用的资源。
诚然,实施可以动态地扩展这些东西。但除非你描述这个特殊案例,否则你永远不会知道。哦,如果它确实动态扩展...那么您也不会 从使用这样的多个队列中获得 很多。
- 让多个队列执行真正的渲染操作没有帮助。
- 拥有一个具有一个或多个计算队列(作为实际计算队列或您提交计算工作的图形队列)的单个渲染队列有助于在渲染操作期间保持执行单元充分饱和。
是的,如果您有高度独立的工作负载,请使用单独的队列。
如果队列之间需要大量同步,它可能会扼杀您可能获得的任何潜在好处。
基本上,在相同队列系列的情况下,您正在做的是为 GPU 提供它可以做的一些替代工作(并填充停顿、气泡和空闲,并为 GPU 提供选择)。并且有更好地使用 CPU 的潜力(例如,单线程与每个线程一个队列)。
使用单独的传输队列(或其他专门的系列)似乎甚至是推荐的方法。
一般来说。 SW 和 NB 的答案已经提出了更现实的、经验的、怀疑的和实用的观点。实际上,人们确实必须更加谨慎,因为这些队列以相同的资源为目标,具有相同的限制和其他常见限制,从而限制了由此获得的潜在好处。值得注意的是,如果驱动程序对多个队列做了错误的事情,它可能对缓存非常不利。
这个 AMD 的 Leveraging asynchronous queues for concurrent execution(2016) 讨论了它如何映射到他们的 HW\driver。它显示了使用单独队列系列的潜在好处。它说虽然他们提供了两个计算系列队列,但他们当时并没有观察到应用程序的好处。他们说他们只有一个图形队列,为什么。
NVIDIA好像也有类似的想法"asynch compute"。显示在 Moving to Vulkan: Asynchronous compute.
为了安全起见,尽管在当前硬件上,我们似乎仍应坚持只使用一种图形和一种异步计算队列。 16个队列似乎是一个陷阱和一种伤害自己的方式。
对于传输队列,它也不像看起来那么简单。您应该使用专用的主机-> 设备传输。而非专用应该用于设备->设备传输操作。
由于您可以在同一个队列中提交多个独立的工作负载,并且它们之间似乎没有任何隐式排序保证,因此您实际上不需要一个以上的队列来使队列族饱和。所以我猜多个队列的唯一目的是允许队列之间有不同的优先级,正如在设备创建期间指定的那样。
我知道这个答案与公认的答案直接矛盾,但那个答案未能解决您不需要更多队列来向设备发送更多并行工作的问题。