出发点
RDMA(提供一种单边内存访问原语(one-sided read/write),允许一个节点在不引入远端节点 CPU 参与的情况下非常高效地访问远端节点的内存(时延仅为2-3微妙)使得内存分离架构成为一种有吸引力的方式来降低数据中心的内存成本。
然而 RDMA 在远程内存管理方面仍然面临着一些挑战。
-
RDMA 内存申请释放的开销非常高(例如,一次内存区域(MR)注册需要超过480微秒),这使得细粒度的内存分配(如4KB、2MB)在性能上难以接受。
-
为了降低内存申请释放的开销,现有的 RDMA-based 分布式内存系统通常采用粗粒度的内存分配(GB级别),这会导致内存浪费。
FineMem 旨在打破上述细粒度分配中的延迟和可扩展性挑战,同时避免内存浪费。同时通过软件的方式实现内存隔离和元数据一致性。
具体来说,FineMem 利用了ConnectX-6的内存窗口(MW)和 SRIOV 的硬件功能来实现高性能、细粒度的内存分配。
- MW 允许以更细粒度的方式生成和失效 rkey(1ms级别)。通过预注册MR(所有节点共享MR rkey)和利用MW机制,成功地从内存分配路径中删除了MR注册的开销,从而降低了内存申请释放的开销。
- 细粒度分配带来的MW不足挑战。ConnectX-6为例,其支持16 million个MW(即64GB的以4KB为单位的内存块)。通过 SRIOV 技术,FineMem 可以在单个 ConnectX-6 NIC 上生成多达 128 个虚拟功能(VF),每个 VF 可以分配 16M 个内存窗口,从而克服了单个 NIC 64GB 内存限制(即8TB的内存池)。
对于我们欧拉实验室来说,接下来依托于UB总线(低时延)的远端内存访问能力,一方面需要多多了解UB的硬件特性能力,看看是否可以通过软件的方式来避免硬件的限制。另一方面,FineMem几乎都是用户态实现的,所以它可以在不修改内核的情况下,灵活地进行优化和调整,无缝集成到现有的内存分配系统(mimalloc)、键值存储系统和swap系统中,展现了很好的可移植性和实用性,这一点非常值得我们学习。
论文总览
本文介绍了FineMem,一个基于RDMA的远程内存管理系统,实现了高性能、细粒度的内存分配。FineMem通过消除RDMA内存区域(MR)注册开销、利用RDMA内存窗口和可信分配服务确保远程内存隔离、采用无锁的单向RDMA协议在计算节点故障时维护元数据一致性,解决了细粒度分配中的延迟和可扩展性挑战。与现有系统相比,FineMem将远程内存分配延迟降低了95%,使内存分配系统、键值存储和交换系统能够以最小开销实现低内存浪费。与大粒度分配相比,FineMem在内存利用率有2.25x到2.8x的提升(2.5%~4.1%的性能劣化)。
背景与动机
现代数据中心为了提升集群范围内的内存利用率、降低部署成本,往往会采用分离式内存(disaggregated memory)架构。这种架构将集群内的计算资源和内存资源进行解耦,划分为具有充足计算资源但仅拥有少量内存资源的计算节点(compute nodes,CN),和具有充足内存资源但算力非常受限的内存节点(memory nodes,MN)。这种架构带来的好处有:(1)内存池化带来的内存利用率提升;(2)两种资源可以分别弹性扩充。 基于单边RDMA的远程访问:RDMA网络提供一种单边内存访问原语(one-sided read/write),允许一个节点在不引入远端节点 CPU 参与的情况下非常高效地访问远端节点的内存(时延仅为2-3微妙)。得益于此,分离式内存架构中一个 CN 可以将自己的数据存储在 MN 上,并在需要时借助 one-sided RDMA 快速将数据取回本地。
RDMA 面临的内存管理挑战:RDMA 的内存管理依赖于一个叫做内存注册 (Memory Region Registration)的控制面原语,MR 注册完成后 MN 将 MR 的地址、大小、rkey 等元数据发送给 CN,随后 CN 可以使用 one-sided RDMA 访问该 MR。由于内存注册过程需要将内存页固定在物理内存中并为 RDMA 网卡准备一张页表,其是一个非常耗时且需要 CPU 参与的过程。因此在分离式内存场景下内存管理面临一个两难困境:
粗粒度的内存注册会带来内存碎片化问题,进而导致远端内存被浪费。
细粒度的内存注册会因为频繁的内存分配请求(基于 RPC)和内存注册带来过高的运行时开销,MN 的有限算力也会成为瓶颈。
设计概要
为了提供高效的细粒度内存管理,本篇论文提出 FineMem。FineMem 的整体架构如上图所示,其将 MN 的全部内存预先注册为一个大的 MR,然后将其切分为细粒度的 chunk(4KB),并使用一个 Two-layer bitmap 作为分配这些 chunks 的元数据。CN 直接通过 one-sided RDMA 访问 bitmap 来进行内存分配。
然而,以上设计依然面临两个问题:
Problem #1:所有 chunk 位于同一个 MR 内部,如何保证不同 CN 之间远程内存的隔离性?
Problem #2:CN 节点崩溃时,如果保证内存管理元数据(bitmap)的正确性?
下文会先描述 FineMem 内存管理元数据的具体细节,然后再描述 FineMem 解决以上两个问题的具体技术方案。
设计细节
当一个 CN 需要进行内存分配请求时,其需要通过 one-sided RDMA 查询用于维护空闲 chunk 的元数据。如上图所示,为了减少查询空闲 chunk 的开销,FineMem 将内存分为 2MB section、128KB span、4KB chunk 三层,并使用一个 two-layer bitmap 来维护内存的分配情况。其中每个 section header 中维护其 16 个 span 的分配状态,每个 span header 中维护其 32 个 chunk 的分配状态。每个 CN 通过 one-sided read 来查询 header,并使用 one-sided CAS (compare-and-swap) 更新 header 来完成内存分配操作。
为了进一步降低内存分配的开销,FineMem 还采取两个优化措施:(1)在每个 CN 引入 header 元数据缓存,只有在 CAS 更新 header 失败时才会更新 header 缓存。(2)每个 span 的分配状态在 section header 中使用两个 bit 来维护,00 和 11 代表其中的 chunk 完全空闲和完全分配,01 代表其处于正常的分配状态,而 10 则代表有多个 CN 在该 span 中进行分配,处于高竞争状态。当一个 CN 在某个 span 中尝试分配 chunk 时多次 CAS 失败,则会将该 span 标记为 10(高竞争)状态。每个 CN 在分配 chunk 时优先从状态为 01 的 span 中进行分配。
Memory Isolation:
由于所有 chunk 处于同一个 MR 内,所以 FineMem 提出了基于 MW(memory window) 的权限隔离机制。一个 MW 可以被非常高效地绑定到预先注册好的 MR 的一小块内存上,此操作耗时仅为 1~3 微妙。FineMem 为每个 chunk 预先创建一个 MW,并为此 MW 预先生成一个 main rkey 和一个 backup rkey。当 CN 释放一个 chunk 时,其用一个 one-sided CAS 将 main rkey 替换为 backup rkey。MN 的 CPU 会异步地扫描所有被释放的 chunk,当发现一个被释放的 chunk时,就使用 backup rkey 将其与 MW 重新绑定,并再次生成一个新的 backup rkey。
为了避免 CN 随意篡改内存管理相关的元数据,FineMem 在每个 CN 上部署一个可信的 Allocation Service 进程,CN 上的应用通过进程间通信(IPC,开销2-10us,相比于微秒级的RPC内存申请释放是完全能接受的)向 Allocation Service 进程发送通知后,由 Allocation Service 进程代为发送远程内存分配请求。
CN-Failure Crash Consistency:
为了保证内存管理元数据在 CN 崩溃时的正确性,FineMem 在 header 中引入 redo log,包括 timestamp,last_id(User ID)等信息。内存分配完成后,CN 分配负责将 redo log 写入到 full log (位于 MN 上的另一片区域)中。当 CN 故障发生时,MN 负责扫描 full log 来回收该 CN 占用的内存资源。
测试结果
End-to-End Performance on Key-Value Store:
FineMem 将其内存管理集成到一个典型的分离式键值存储系统 FUSEE(FAST'23)中,并测试 YCSB-A 的性能,YCSB-A 中的 out-of-place update 操作会引入远程内存分配。如下图所示,相比于 Premmap-RPC,FineMem 可以带来 27% 到 110% 的吞吐率提升,提升主要来源于 更高效的远程内存分配。
End-to-End Performance on Swap System:
FineMem 将其内存管理集成到一个典型的基于 kernel swap 的远程内存系统 Fastswap (Eurosys'20)中,并测试不同 workload 混合部署在 CN 上的运行性能(XGBoost:Snappy:Redis=2:2:1)。得益于 FineMem 的细粒度分配,相比于 Fastswap(为每个 CN 预先注册 32GB 内存),其能够提升 74.06% 的内存利用率。得益于更优的内存利用率,FineMem 带来了 17.71% 的总吞吐率提升。

知识点补充
分离式内存架构(Disaggregated Memory Architecture)
分离式内存架构(Disaggregated Memory Architecture)是一种新兴的内存管理方式,它将内存资源从计算节点中分离出来,形成一个共享的远程内存池。这种方式可以提高内存利用率,降低内存成本。
RDMA远程内存管理系统
RDMA远程内存管理系统是一种新兴的内存管理方式,它通过RDMA技术将内存资源从计算节点中分离出来,形成一个共享的远程内存池。这种方式可以提高内存利用率,降低内存成本。
RDMA支持两种通信模式:远程过程调用(RPC)和一侧的直接远程内存访问。一侧的远程内存访问需要在RDMA网卡上进行内存区域(MR)注册,这个过程会引入显著的延迟开销。
现有的远程内存管理系统通常采用粗粒度的内存分配(GB级别),这会导致内存浪费。而细粒度的内存分配(如4KB、2MB)则面临着延迟和可扩展性的挑战。
内存节点CPU能力较弱,无法处理频繁的内存分配请求和MR注册。
虽然RMDA在数据中心有着巨大的潜力,但是在分离式内存架构(DM)中,内存申请释放依然面临着巨大的挑战。
从内存节点(Memory Node,MN)分配内存涉及以下几步:
- 通过mmap分配一段内存区域(pre-fault 物理页)。
- 将页表条目注册并复制到RNIC的内存事务表(MTT)中。
- 在RNIC上生成具有访问能力的内存管理单元,称为内存区域(Memory Region,MR),并分配一个rkey。
这些操作都需要在内存节点的CPU上完成,是一个非常耗时的过程。例如注册一个4MB的内存区域就需要超过480微秒的时间。这种RDMA内存注册的高开销,是RDMA-based分布式内存系统面临的主要挑战之一。所以传统的分布式内存系统通常采用粗粒度的内存分配(GB级别)来分担分配开销,但是这种粗粒度的内存分配会导致内存浪费。
内存窗口(Memory Window,MW)
内存窗口(Memory Window,MW)是RDMA的一种硬件功能,它允许以更细粒度的方式生成和失效rkey(1ms级别)。
以ConnectX-6为例,其支持16 milion个MW(即64GB的以4KB为单位的内存块)。同时ConnectX-6还支持SRIOV,最多可以支持128个VF,这样共计支持128 * 16 million = 2 trillion个MW,即8TB的内存池。