Peer to Peer DMA

点对点DMA

在2023年“Linux存储、文件系统、内存管理和BPF峰会”的首日全体会议上,Stephen Bates主持了一场关于“点对点DMA(P2PDMA)”的讨论。这个想法的核心在于,从一个连接了PCIe的设备向另一个设备传输数据时,消除主机系统的介入。这最初是针对NVMe SSD设计的,以便数据可以直接在存储设备之间进行直接复制,而无需将其移动到系统内存,然后再从内存传输到其它地方。

背景信息

Bates表示,这个想法可以追溯到大约2012年,当时他和Logan Gunthorpe正在研究NVMe SSD、RDMA和NVMe over Fabrics(在成为标准之前)。一些客户建议能够在设备之间直接进行DMA传输将会很有用。通过暴露一些内存的设备(今天称为”控制器内存缓冲区”或CMB,Controller Memory Buffer),他们成功地实现了P2PDMA的前身。该功能有一些用户空间(user-space)中的实现,包括用于SPDK和NVIDIA的GPUDirect Storage,后者允许在NVMe命名空间和GPU之间直接进行复制。

传统的DMA在两个PCIe设备之间传输数据时存在一些缺点,比如在NVMe SSD和RDMA网卡之间。所有DMA操作都从其中一个设备进入系统内存,然后必须从系统内存复制到另一个设备,这会使所需的内存通道带宽翻倍。如果用户空间应用程序也试图访问与DMA操作相同物理DIMM上的RAM,还可能出现各种各样的服务质量问题。

他说,P2PDMA避免了这些问题,但也带来了一些挑战。最初的Linux P2PDMA实现仅限于内核内部;虽然有一些允许来自用户空间访问的极客方法,但从未被合并到主线。然而,最近的6.2内核已经支持在某些情况下从用户空间访问P2PDMA。P2PDMA在NVMe驱动程序中可用,但只有具有CMB的设备才能作为DMA源或目标。目前,NVMe设备是唯一支持DMA主设备的系统。

Bates不确定Arm64是否是一个完全支持的体系结构,因为存在着Gunthorpe正在解决的”一些奇怪问题”,但x86得到了充分的支持。IOMMU(Input/Output Memory Management Unit)在P2PDMA中扮演了重要角色,因为它需要在不同系统之间翻译各种类型的物理和虚拟地址;”实际上,将DMA定向到错误的位置绝不是一件好事”。IOMMU还可以扮演一个安全角色,以确保不会实际执行错误的DMA操作。

目前,正在对工作正常和工作不正常的设备进行允许列表和阻止列表的制定中,不过总体情况正在逐步改善。也许是因为GPUDirect的努力,CPU和PCIe设备对P2PDMA的支持似乎正在变得更好。他提到了他的p2pmem-test存储库,用于在虚拟机(VM)中测试这个特性的用户空间组件。据他所知,除了NVMe驱动程序之外,目前没有其它PCIe驱动程序实现P2PDMA。

未来展望

大多数NVMe驱动程序是通过逻辑块地址(LBA,Logical Block Addresse)访问的块设备,但也有一些具备对象存储功能的设备。同时,即将推出计算型存储接口,用于对设备上的数据进行计算(例如压缩)。此外,还会推出支持字地址存储的NVMe命名空间;这些不是”加载-存储接口”,不像RAM那样可以通过加载和存储指令从CPU访问,而是以字节粒度提供的存储接口。在未来可能会支持将P2PDMA应用于NVMe持久内存区域(PMR,Persistent Memory Region),该区域可通过加载-存储方式访问,并由某种持久数据(例如备电支持的RAM)支持,尽管他尚未听说有任何正在开发的NVMe PMR驱动。他表示,PMR设备可能会与CXL的使用场景重叠。

正在改进对虚拟机(VM)和IOMMU的支持。PCIe具有各种处理和缓存内存地址转换的机制,这些机制可以用于改进P2PDMA。增加QEMU(Quick Emulator)的更多功能(例如SR-IOV)很重要,因为使用真实硬件调试问题很困难。架构支持也很重要;可能仍然存在Arm64支持的问题,但其它重要的架构,如RISC-V,也需要添加P2PDMA支持。

在上一届会议上CXL被重点解读,因此Bates表示他想深入研究一下。P2PDMA是在CXL不存在的情况下出现的,但现在它存在了,他认为在CXL世界中有一系列有意义的P2PDMA场景。在电气上和物理方面,CXL与PCIe相同,这意味着两种类型的设备都可以插入同一个总线插槽。它们在数据链路层上是不同的,但已经在CXL.io上做了一些工作,可以将PCIe转换为CXL。

这意味着具备对CXL流控制单元(flits)的支持的NVMe驱动可以插入CXL端口,并且可以通过主机上的NVMe驱动程序将其用作存储设备。他和一位同事在上周使用QEMU对此进行了建模,这可能是第一次实现这一点。他相信这是有效的,但需要进行更多的测试。

在CXL 3.0之前,直接在CXL内存和NVMe固态硬盘之间执行P2PDMA并不容易,因为存在缓存一致性问题。CXL 3.0引入了一种方法,让CXL能够告知CPU即将在特定的物理内存区域执行DMA操作,并要求CPU从其缓存中更新CXL内存。无序I/O(UIO)功能增加了这种能力,可以以硬件速度在存储设备之间传输大块数据,而不会影响CPU或其内存互连。与存储设备不同,可以使用NVMe网络设备将数据直接从CXL内存传输到网络。

Bates表示,这种类型的点对点传输变得越来越受欢迎,尽管许多人并未使用P2PDMA来完成这些操作。随着时间的推移,这种受欢迎程度可能会转化为更多的P2PDMA用户。(此时,LSFMM+BPF组织者Josef Bacik指出,该时段已过,因此内存管理人员需要前往下一场会议,而存储和文件系统开发人员继续进行讨论。)

David Howells问Bates是否与图形开发人员讨论过P2PDMA,因为似乎他们可能有兴趣使用它将数据(例如纹理)从存储移到GPU。Bates表示,他一直专注于云和企业级的场景,因此尚未联系图形开发人员。大型AI集群正在使用对等传输到GPU,尽管通常是通过GPUDirect机制实现的。

Bates表示,最近NVMe社区一直在定义新类型的命名空间。目前,LBA命名空间占据了99%的使用率,但正如他之前所指出的,还有其它类型的命名空间即将推出。所有这些命名空间类型和命令集都可以在PCIe和CXL上使用,但也可以在RDMA或TCP/IP等协议下用于面向传统存储设备的数据传输。虽然尚未成为标准的一部分,但他希望能够提供一种方法,将NVMe命名空间(或其子区域)呈现为字节可寻址的加载-存储区域,以供P2PDMA利用。

在这些操作中,”加载-存储”与DMA的含义产生了一些分歧。Bates表示,对于访问设备上的数据,DMA意味着将某种描述符发送到数据传输器,该传输器将根据指定的要求移动数据,而”加载-存储”则意味着CPU参与进行一系列的加载和存储操作。因此,可以有一个新的NVMe命令,请求将区域暴露为CMB、PMR,或者”我们尚未发明的新东西”;然后CPU(或其它设备,例如DMA数据传输器)可以对该区域进行加载-存储访问。

他描述了一个使用情景,即在NVMe SSD上拥有一个极热门(即频繁访问)的大文件,但希望能够通过加载和存储直接访问它。通过几个简单的NVMe命令,可以准备好这些数据,以便以字节可寻址的方式访问,然后可以使用mmap()将其映射到应用程序的地址空间中;这将类似于在内存中拥有文件,而在访问时不会出现页面错误。