图片无法显示,请右键点击新窗口打开图片

在传统计算机架构里,共享内存往往指的是同一台主机内存,两个 CPU 之间共享同一块物理内存,这里可以是两个用户进程之间通过一定的共享机制实现内存共享,也可以是用户进程用户态和用户进程内核态之间使用内存映射达到内存共享. 随着技术的不断进步,内存共享这个概念被不断扩大,例如在两个主机之间实现物理内存共享,可能会有童鞋说可以使用 RDMA 实现两个主机之间资源共享,但这样的共享需要涉及内存拷贝,真正共享是不存在任何内存拷贝就可以访问同一块物理内存.

图片无法显示,请右键点击新窗口打开图片

CXL 提供了 Sharing 模式来实现池化资源的共享,Sharing 模式允许多个主机或设备同时访问同一个资源,并确保这些资源的一致性和高效使用. 这种共享机制能够确保多个主机设备能够在不互相干扰的情况下访问和操作相同的资源,比如内存和加速器. CXL 使用一致性协议(如 CXL.cache 和 CXL.mem)确保在共享模式下,所有设备能够看到同一个资源的最新状态,从而避免数据不一致问题, Sharing 模式具有以下特点:

  • 多主机并发访问: 多个主机可以同时访问共享的内存或加速器资源, 每个主机都能够访问该资源的不同部分,或者通过一致性机制访问同一数据
  • 缓存一致性: 通过 CXL.cache 协议,设备之间能够保持数据的一致性, CXL 的一致性协议确保每个设备在共享资源时不会因为数据冲突或访问冲突导致错误
  • 低延迟共享: CXL 提供了低延迟的内存访问,即使多个主机同时访问共享资源,也可以保证高效的传输和访问

图片无法显示,请右键点击新窗口打开图片

CXL 需要实现 Sharing 池化功能,那么硬件上必须包括: CXL SWITCH、CXL Type3 设备(MH-SLD/MH-MLD) 以及 Fabric Manager. 协议上必须支持 CXL2.0 及其以上, 每种硬件组件在 Sharing 模式下的作用如下

  • CXL.cache 协议: CXL.cache 协议提供缓存一致性支持, 多个主机在访问共享内存时,通过 CXL.cache 保证缓存的一致性. 共享的资源在任何一个主机上被修改时,其他主机可以立即获得最新的数据, 这对于加速器(如 GPU)和 CPU 之间共享内存来说尤为重要.
  • CXL.mem 协议: CXL.mem 协议支持多个设备对共享内存的直接访问. 主机和设备可以直接通过 CXL.mem 访问共享内存区域,允许多个主机同时读写共享的内存区域, CXL.mem 协议确保多个主机能够安全地共享内存资源
  • 共享内存模型: 在 Sharing 模式下,内存可以配置为共享内存,允许多个主机或设备同时访问, 这种共享机制能够大大提升资源的利用率,并减少内存冗余。共享内存可用于并行计算和高性能计算等场景
  • Fabric Manager 的协调: Fabric Manager(FM) 是管理资源共享的关键组件, 它负责协调多个主机和设备之间的资源共享,确保访问的顺序、资源的分配和释放、以及数据的一致性管理. 通过 FM,可以在多主机环境下实现高效的共享资源调度

通俗来讲,对于 CXL Type3 设备要实现 Sharing 模式,那么 MH-SLD/MH-MLD 的特性是必不可少的,其可以让多个主机端口连接到同一个 SLD/MLD 设备上,这就向其名字 “Multi-Headed” 一样,虚拟出多个端口让多个主机 VH 的 vPPB 进行连接. Sharing 模式的优点是:

  • 提高资源利用率: 在 CXL Sharing 模式下,多个主机或设备可以同时使用同一资源(如内存或加速器),这意味着无需为每个主机单独配置资源. 这大大提高了资源的利用率,避免了硬件资源的浪费.
  • 降低数据复制开销: 传统系统中,多个主机间共享数据通常需要将数据复制到各自的内存中,而 CXL 的 Sharing 模式通过共享内存区域,避免了数据的冗余复制, 这样不仅减少了数据传输开销,还提升了系统的性能
  • 并行处理: Sharing 模式特别适合并行处理场景,尤其是在高性能计算(HPC)和机器学习等应用中, 多个计算节点可以并行访问共享的数据,极大地提升了并行处理效率
  • 简化编程模型: 通过共享内存,开发人员可以更轻松地实现多个主机之间的数据共享,而不必依赖复杂的通信协议或数据同步机制, 这简化了编程模型,使得高效的数据访问变得更加简单
CXL Sharing Practice

图片无法显示,请右键点击新窗口打开图片

BiscuitOS 提供了 CXL Sharing 的实践环境,其 CXL 拓扑如上图, BiscuitOS 使用两个虚拟机作为两个服务器主机,并使用 QEMU 的 QMP 充当 Fabric Manager(FM). 在初始状态下,CXL Type3 设备作为 MH-MLD 设备并绑定到两个主机的 VH 上. 在两个主机上电之后,FM 可以根据需求将 MH-MLD 绑定到指定 VH 的 vPPB 上,也可以从指定 VH 的 vPPB 上进行解绑. 接下来在 BiscuitOS 上进行实践, 请参考如下命令:

# 切换到 BiscuitOS 项目目录
cd BiscuitOS
# 选择开发环境,如果已经选择过可以跳过,这里与 linux 6.10 X86 为例
make linux-6.10-x86_64_defconfig
# 通过 Kbuild 选择需要部署的应用程序
make menuconfig

  [*] DIY BiscuitOS/Broiler Hardware  --->
      [*] CXL: Compute Express Link
            CXL Hardware Topology (CXL2.0: x2 Host(VH) + MH-MLD)  --->
  [*] Package  --->
      [*] HETEROGENEOUS MEMORY MANAGEMENT
          [*] CXL MH-MLD: Multi Headers MLD  --->

# 配置完毕保存,然后进行部署
make

# 切换到实践案例所在目录
cd output/linux-6.10-x86_64/package/BiscuitOS-CXL-MHMLD-default
# 准备依赖工具
make prepare
# 编译实践案例
make download
make build

图片无法显示,请右键点击新窗口打开图片

当第一个主机启动之后,使用 cxl 命令查看 CXL 拓扑结构,可以看到已经绑定的两个 CXL Type3 设备,接着使用 lspci 命令查看 PCIe 总线,可以看到 CXL SWITCH(BDF 0E:00.0) 之下有绑定的 CXL Endpointer 设备. 接下来新启动一个终端来启动第二个主机,参考如下命令:

# 切换到 BiscuitOS 项目目录, 同理以 linux 6.10 X86 为例
cd BiscuitOS/output/linux-6.10-x86_64
# 直接启动第二个主机
./RunBiscuitOS-CXL.sh

图片无法显示,请右键点击新窗口打开图片

当第二个主机启动之后,使用 cxl 命令查看 CXL 拓扑结构,可以看到 MH-MLD 对应的 CXL Type3 设备被识别到,接着使用 lspci 命令查看 PCIe 总线,可以看到 CXL SWITCH(BDF 0E:00.0) 之下绑定 MH-SLD 的 CXL Endpointer 设备. 此时两个主机已经环境已经部署完毕,两个主机 VH 的 vPPB 都绑定同一个 MH-MLD, 一共两个 MH-MLD 设备, 接下来在两个主机上使用同样的命令初始化 CXL Type3 设备,然后同时对共享内存进行访问,使用如下命令:

图片无法显示,请右键点击新窗口打开图片

  • cxl create-region -d decoder0.0 -m mem0 -s 512M -t ram -w 1 -g 4096 -u: 命令用于创建一个 CXL Region
  • cxl enable-region region0: 创建完毕之后使用该命令使能 CXL Region
  • daxctl reconfigure-device –mode=devdax dax0.0 –force: 将 CXL Type3 设备模式修改为 DEVDAX
  • BiscuitOS-CXL-SLD-default READ: 从 CXL Type3 设备上读取数据
  • BiscuitOS-CXL-SLD-default WRITE <MESSAGE>: 向 CXL Type3 设备写入数据

执行完这些命令之后,可以看到主机一可以正常访问 MH-MLD 映射的 CXL Type3 设备,主机一并向设备写入 “2024-10-04-18-12”, 此时主机二可以直接读取到 “2024-10-04-18-12” 字符串,同理主机二写入 “THIS IS HOSTB”, 主机一可以直接读到 “THIS IS HOSTB”. 以上便是 MH-MLD 实现的 CXL Type3 设备池化共享机制. CXL Sharing 实践至此结束

图片无法显示,请右键点击新窗口打开图片