【问题标题】:Is there a way to map a host-cached Vulkan buffer to a specific memory location?有没有办法将主机缓存的 Vulkan 缓冲区映射到特定的内存位置?
【发布时间】:2020-05-19 17:31:43
【问题描述】:

Vulkan 能够使用VkImportMemoryHostPointerInfoEXT 导入主机内存。我查询了VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT 支持的内存类型,但唯一可用的内存是连贯的,这不适用于我的用例。出于性能原因,内存需要使用显式失效/刷新。所以真的,我不希望 API 分配任何主机端内存,我只想告诉它缓冲区应该上传/下载到的基地址。否则我必须使用中间副本。将 vkMapMemory 返回的地址用于主机端工作对于我的用例来说是不可取的。

【问题讨论】:

  • “主机缓存”是指“主机支持”,还是 Vulkan 中的 CACHED 类型?
  • @krOoze 我想我对 Vulkan 很陌生,所以也许我使用的术语有误,但基本上我想在 CPU 和 GPU 之间镜像内存,这样我就可以在没有隐式 PCI-e 总线传输。我正在使用它的项目模拟具有统一内存的系统,如果每次读/写都会导致总线传输,那么性能很快就会消失。因此,当客户 CPU/GPU 访问重叠区域时,我只需要向主机 GPU 发送数据或从主机 GPU 发送数据。
  • @MarshallMohror:“我想在 CPU 和 GPU 之间镜像内存,这样我就可以在没有隐式 PCI-e 总线传输的情况下访问它。”但是在独立 GPU,任何内存都存在于来自至少 一个 设备的 PCI-e 总线上。如果两个设备共享一些内存地址,并且一个设备跨过来自该内存的总线,那么 其中一个设备 访问该内存的速度将变慢。 Vulkan 允许您选择哪一个,但如果 GPU 是离散的,则不能让它“两者都不是”。

标签: vulkan memory-mapping


【解决方案1】:

如果 Vulkan 实现不允许您将内存分配导入为“CACHED”,则您不能强制这样做。 API 为实现提供了宣传将您的分配导入为“CACHED”的能力的机会,但实现明确拒绝这样做。

这可能意味着它不能。而且你不能让实现做它不能做的事情。

因此,如果您有一些 API 创建和操作一些内存(不能使用其他人提供的内存),并且 Vulkan 实现将不允许从该内存中读取,除非允许删除分配的缓存性质,并且您需要对该内存进行 CPU 缓存,那么您将不得不求助于 memcpy


我想在 CPU 和 GPU 之间镜像内存,这样我就可以在没有隐式 PCI-e 总线传输的情况下从任何一个访问它。

如果 GPU 是离散的,那不可能。在离散 GPU 设置中,GPU 和 CPU 具有独立的本地内存池,并且从另一个池访问任一池需要某种形式的 PCIe 传输操作。 Vulkan 让您选择哪一个访问速度较慢,但​​其中一个访问内存较慢。

如果 GPU 是集成的,那么通常只有一个内存池和一种内存类型。该类型既是本地的又是连贯的(并且可能也是缓存的),这表示从两个设备都可以快速访问。

【讨论】:

  • 我不确定您的第一段与该问题有何关系。 Q 说它想要非连贯的内存,但主机指针的导入只允许作为连贯的。这对我来说有点道理,因为 C\C++ 中的普通堆内存本质上是一致的。
  • @krOoze:“Q 说它想要非连贯记忆”重新阅读问题。 OP 说他们想要 cached 内存。他们希望 CPU 快速访问内存;这是否也涉及“连贯”访问不是重点。我的观点是 API 具有允许实现允许您将内存作为“缓存”导入的工具,所以如果它不允许您这样做,那可能是因为它不能。
  • Q 标头中只提到了“缓存”,并且似乎与您解释的 Q 内容无关。无论如何,我会问提问者。
  • 我想你还是误解了我想要什么。我只想要两个单独的内存块,我想选择何时在它们之间发送数据。我不希望两个设备都访问同一个内存块。
  • @MarshallMohror:如果你想要两个单独的内存块,你为什么要问一个专门让 Vulkan 直接访问你分配的内存块的功能?您能否重述您的问题,以更清楚地准确地了解您想要实现的过程?
【解决方案2】:

无论是VkImportMemoryHostPointerInfoEXT 还是vkMapMemoryDEVICE_LOCAL_BIT 堆,您通常会得到COHERENT 内存类型。

因为,C 中 malloc 的传统主机堆内存自然是一致的(并且 CPU 通常具有自动缓存一致性机制)。 C中没有cflush()cinvalidate()

当从主机端 R\W 此类内存时,没有理由进行隐式 PCI-e 传输。当然,专用 GPU 必须以某种方式读取它,因此当设备尝试访问内存时会有总线传输。或者您需要在DEVICE_LOCAL_BIT 堆中有一个显式内存,并通过vkCmdCopy* 在两者之间显式传输数据以保持它们相同。

实际的 UMA 架构可能具有非COHERENT 内存类型。但是他们的内存堆总是被宣传为DEVICE_LOCAL_BIT(即使它是主内存)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-12
    • 2017-12-09
    • 1970-01-01
    相关资源
    最近更新 更多