【问题标题】:Device to device copy in VulkanVulkan 中的设备到设备复制
【发布时间】:2018-10-04 01:56:30
【问题描述】:

我想在我的 Vulkan 应用程序中的两个 GPU/物理设备之间复制图像/缓冲区(一个 vkInstance,两个 vkDevices)。如果没有在 CPU 上暂存图像,这是否可能,或者是否有像 CUDA p2p 这样的功能?这看起来如何?

如果需要在主机上登台,那么最佳方法是什么?

【问题讨论】:

  • 您好,欢迎来到 StackOverflow!为了获得更好的答案,并且您的答案以后不会被删除,您必须阅读并遵循一些基本规则和约定,以帮助每个人更好地沟通和提供帮助。请转至stackoverflow.com/help 并阅读主题“我可以在这里问哪些主题?”和“我应该避免问哪些类型的问题?”。

标签: c++ gpu vulkan


【解决方案1】:

有像CUDA p2p这样的功能吗?

Vulkan 1.1 支持device groups 的概念来涵盖这种情况。 它允许您将一组物理设备视为单个逻辑设备,还允许您查询如何在设备组中操作内存,以及在设备子集上分配内存等操作。检查完整功能集的规格。

如果不将图像暂存到 CPU 上,这是否可能

如果您的设备不支持扩展VK_KHR_device_group,则不支持。您必须通过 CPU 和系统内存传输内容。

由于缓冲区是每个设备的,因此您需要两个主机可见的暂存缓冲区,一个用于读取操作,另一个用于写入操作。您还需要两个队列、两个命令缓冲区等...

您必须通过手动同步执行 3 个操作。

  • 在源 GPU 上执行从设备本地缓冲区复制到同一设备的主机可见缓冲区。

  • 在 CPU 上从源 GPU 主机可见缓冲区复制到目标 GPU 主机可见缓冲区

  • 在目标 GPU 上从主机可见缓冲区复制到设备本地缓冲区

确保检查您的设备队列系列属性,并尽可能使用标记为支持传输但图形或计算能力的队列系列中的队列。 Vulkan 队列家族拥有的标志越少,它就越适合它确实有标志的操作。大多数modern discrete GPUs 都有专用的传输队列,但同样,队列是特定于设备的,因此您需要与每个设备的一个队列交互才能执行传输。

如果需要在主机上登台,那么最佳方法是什么?

具体如何执行取决于您的用例。如果您想在单个线程中同步执行整个事情,那么您只需进行一堆提交,然后在栅栏上等待。如果您想在继续渲染帧的同时在后台异步执行此操作,那么您仍将执行提交,但您必须在栅栏上进行非阻塞检查以查看操作何时完成,然后再移动到下一部分。

如果您正在传输缓冲区,则在最佳传输方面可能没有什么可担心的,但如果您正在处理图像,那么您必须进入整个线性与最佳图像平铺的混乱局面。为了避免这种情况,我建议使用主机可见缓冲区进行暂存,无论您是传输图像还是缓冲区,因此使用 vkCmdCopyImageToBuffervkCmdCopyBufferToImage 在本地设备和主机可见之间进行传输记忆

【讨论】:

  • "如果设备以某种方式(如 SLI)绑定在一起,则可能支持设备到设备的复制。" 从技术上讲,共享外部存储器可用于非 SLI 情况。但这要求两个设备是相同的硬件(deviceUUIDdriverUUID 必须匹配)。也就是说,您不必将它们使用作为 SLI 设备,但理论上它们必须能够以这种方式使用。
  • 是的,我重新阅读了我的资料,并意识到我可能在暗示 SLI 是必需的,而我的意思只是作为一个潜在的例子,所以我从我的回复中编辑了它。感谢您的反馈。
  • @Jherico 太棒了,这正是我想要的。使用VK_KHR_external_memory 时是否有任何注意事项,因为它不允许您在单独的物理设备上共享内存?我正在与每个 GPU 运行单独实例的 OpenGL 应用程序交互。
  • 您只需要通过在 GL 端查询 DEVICE_UUID_EXTDRIVER_UUID_EXT 来将 GL 上下文与相应的 Vulkan 设备匹配。请记住,由于GL_EXT_external_objects 的实现存在错误,我无法在我的 AMD 系统上获得互操作性。我目前正在研究 OpenGL 互操作性示例:github.com/jherico/Vulkan/blob/gl_test2/examples/glinterop/…
猜你喜欢
  • 2017-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-29
  • 2020-09-11
  • 2013-04-08
  • 2023-03-29
相关资源
最近更新 更多