IOMMU非常有用,因为它提供了一组映射寄存器。它可以安排任何物理内存出现在设备上可访问的地址范围内的任何物理内存,并且也可能导致物理散射的缓冲区与设备看起来连续。这对第三方PCI/PCI Express卡或试图访问NVIDIA GPU的原始物理偏移的远程机器不利,因为这可能不会导致 实际上 访问预期的内存区域或由IOMMU单元以每张XARD限制/限制/限制此类访问。因此,必须禁用这
“ Gpudirect的RDMA目前依赖 从PCI设备的角度来看,所有物理地址都是相同的."
-nvidia, RDMA和GPUDIRECT的设计注意事项
当驾驶员尝试利用CPU的MMU和映射内存映射I/O(MMIO)的映射区域以在内核空间内使用时,他们通常将返回的地址从内存映射到自己的内存映射中。因为每个驱动程序都在其自己的上下文或名称空间内运行,所以在NVIDIA的驱动程序和其他希望支持RDMA+GPUDIRECT的驱动程序之间交换这些映射将非常困难,并且会导致供应商特定的解决方案(甚至可能是产品的产品 - 特定于第三方产品之间的驱动因素会大不相同)。此外,当今的操作系统目前没有任何良好的解决方案来交换驱动程序之间的MMIO映射,因此NVIDIA导出了几个功能,这些功能使第三方驱动程序可以轻松地从内核空间内的内核空间轻松访问此信息。
NVIDIA强制使用“物理地址”通过RDMA访问GPudirect的每张卡。这大大简化了将数据从一台计算机转移到远程系统的PCI-Express BUS的过程,而不必担心与虚拟地址有关的问题(例如将虚拟地址解析到物理上的地址)。每张卡都有一个物理地址所在的物理地址,可以在此偏移时访问;只需将一小部分逻辑添加到试图执行RDMA操作的第三方驱动程序中。另外,这32或64位的基础地址寄存器是标准PCI配置空间的一部分,因此可以通过简单地从酒吧阅读而不是必须获得NVIDIA驱动程序获得的映射地址来轻松获得卡的物理地址连接到卡后。 NVIDIA的通用虚拟寻址(UVA)将上述物理地址映射到看似连续的内存区域 用户空间 像这样的应用程序:
这些记忆区域进一步分为三种类型:CPU,GPU和免费的,它们都记录在案 这里.
但是,回到您的使用情况:因为您在 用户空间, ,您无法直接访问系统的物理地址空间,并且您使用的地址可能是Nvidia的UVA提供的虚拟地址。假设没有进行以前的分配,则您的内存分配应位于Offset +0x00000000,这将导致您看到GPU的相同偏移本身。如果您要分配第二个缓冲区,我想您会在第一个缓冲区结束后立即开始(在offset +0x00100000)开始 虚拟地址 在您的1 MB分配的情况下,GPU的)。
如果你在 内核空间, 但是,并且正在为您的公司卡编写驱动程序来利用RDMA进行GPUDIRECT,您将使用系统的BIOS和/或OS分配给GPU的32或64位物理地址直接与RDMA数据直接从GPU,本身。
此外,可能值得注意的是,并非所有DMA发动机实际上都支持转移的虚拟地址 - 实际上,大多数都需要物理地址,因为处理DMA引擎的虚拟地址 可以变得复杂 (第7页),因此许多DMA引擎对此缺乏支持。
但是,要回答您帖子标题的问题:NVIDIA当前仅支持RDMA+GPUDIRECT的物理地址 在内核空间. 。为了 用户空间 应用程序,您将始终使用NVIDIA的UVA给您的GPU的虚拟地址,该地址在CPU的虚拟地址空间中。
关于您的应用程序,这是您可以为RDMA操作所做的过程的简化分解:
- 您的 用户空间 应用程序创建缓冲区,该缓冲区处于统一虚拟地址空间NVIDIA提供的范围(虚拟地址)。
- 打电话
cuPointerGetAttribute(...)
获得P2P令牌;这些令牌与CUDA上下文中的内存有关。 - 将所有这些信息发送给 内核空间 不知何故(例如,读/写给您的驱动程序等)。至少,您将需要这三件事,最终进入您的 内核空间 司机:
- P2P令牌(S)返回
cuPointerGetAttribute(...)
- 缓冲区的UVA虚拟地址(ES)
- 缓冲区的大小
- P2P令牌(S)返回
- 现在,通过调用NVIDIA的内核空间函数,将这些虚拟地址转换为相应的物理地址,因为这些地址在NVIDIA的页面表中保存,并且可以通过Function的Nvidia的导出,例如::
nvidia_p2p_get_pages(...)
,nvidia_p2p_put_pages(...)
, , 和nvidia_p2p_free_page_table(...)
. - 使用上一步中获得的这些物理地址来初始化您的DMA引擎,以操纵这些缓冲区。
可以找到这个过程的更深入的解释 这里.