目录

xDSM

xDSM 是一套面向跨节点共享内存环境的高性能远程调用运行时。项目以 pthread_create()/pthread_join() 兼容接口为应用入口,将一次远程调用组织为:

create -> execute -> shared object access -> result -> join/cleanup

xDSM 将轻量控制路径与业务数据路径分离。控制消息只携带函数入口、参数地址和必要 的目标信息;参数对象、内部指针和结果对象保留原生内存布局,由目标节点上的 worker 通过共享地址空间直接访问。运行时还可在不改变对象虚拟地址的前提下,在 CXL 共享 内存和本地 DRAM 之间调整页面驻留位置。

本项目重点解决以下问题:

  • 缩短共享内存环境中的远程调用软件路径;
  • 支持包含字符串、动态数组、嵌套指针和图结构的复杂对象跨边界访问;
  • 建立 createexecutejoincleanup 完整线程生命周期;
  • 在统一调用接口下支持 CXL 直接访问、本地移动、本地只读复制和回迁等页面路径。

核心设计

全地址空间共享执行环境

xDSM 保存并在目标节点原地址恢复必要的进程映像,使函数入口、全局符号和运行环境 具有一致的虚拟地址语义。需要跨节点读写的动态对象位于 xDSM 管理的共享对象区, 由固定地址映射和 mapping record 维护。

全地址空间共享不表示所有普通 VMA 都自动成为跨节点可写共享映射。进程映像恢复 负责让代码和运行环境能够被目标节点解释;xDSM 共享对象区负责承载需要跨节点读写 的业务对象。

动态页面放置

应用和远端 worker 始终使用相同虚拟地址访问对象。运行时根据页面访问状态在以下 路径间调整物理驻留位置:

  • CXL direct:页面保留在 CXL 共享后端;
  • local move:单节点热点页移动到该节点本地 DRAM;
  • local copy:读多写少页面复制到多个节点的本地 DRAM;
  • demote:本地页面失去收益后撤销或写回 CXL 共享后端。

页面放置只改变页面的物理位置和 PTE 指向,不改变 VMA、对象虚拟地址或内部指针。

代码结构

路径 作用
src/dt.cinclude/dt.h 远程线程创建、请求提交、执行、join 和 cleanup
src/mm.cinclude/mm.h 固定地址映射、mapping record 和共享内存分配
src/dt_io.csrc/io.c 固定大小控制消息和节点间通信
src/cr.csrc/ckpt.c 进程映像保存、恢复及 /dev/ckpt 用户态封装
src/shim.cwrap/ pthread 与内存接口接管、运行时自动初始化
src/mx-sc/ xDSM-SC 页面状态、复制、独占、失效与回迁
src/mx-rc-wt/src/mx-rc-wb/ xDSM-RC 相关实现
ckpt_mm/ 页表和地址空间操作的 Linux 内核辅助组件
config/config.h 逻辑节点、CPU 亲和性和 NUMA 映射
include/common.h 共享容量、共享文件路径和运行时公共配置
bench/ PageRank、Graph500、KV、Streamcluster、MoE 等应用
test/ 内存、线程、通信和页面机制测试
scripts/ NUMA/CXL 内存后端和性能观测辅助脚本

项目不需要单独启动常驻 RPC 服务端。应用加载 xDSM 运行库后,src/shim.c 会完成 运行时初始化和服务进程派生。

运行环境

已验证环境

  • Ubuntu/Linux;
  • Linux 6.3 定制内核;
  • CONFIG_CKPT_MM=yckpt_mm 直接编入内核;
  • /dev/ckpt 字符设备;
  • 真实 CXL 1.1 Type-3 内存,配置为 memory-only NUMA;
  • 使用同一服务器上的 NUMA 节点模拟四个逻辑计算节点;
  • GCC、CMake、GNU Make、Bash、pthread、libnuma、libdl、libatomic 和 libm。

当前实验不是实际的 CXL 3.0 多主机部署。迁移到其他服务器时,需要根据机器的 CPU、NUMA 和共享内存拓扑修改编译期配置。

软件依赖

Ubuntu 环境可安装以下基础依赖:

sudo apt update
sudo apt install build-essential cmake libnuma-dev numactl

完整运行需要 root 权限,用于创建共享内存后端、调整系统参数、清理页缓存以及访问 内核和性能采样接口。

快速运行

以下步骤适用于已经启动定制内核、创建好共享内存文件并完成拓扑配置的服务器。

1. 检查环境

uname -r
grep CONFIG_CKPT_MM /boot/config-"$(uname -r)"
test -c /dev/ckpt && echo "ckpt device: ready"

numactl --hardware
ls -lh /mnt/raminterleave4_5/dax

cat /proc/sys/kernel/randomize_va_space
cat /proc/sys/kernel/numa_balancing
cat /proc/sys/vm/max_map_count

预期条件如下:

  • CONFIG_CKPT_MM=y
  • /dev/ckpt 存在且当前用户可通过 sudo 访问;
  • /mnt/raminterleave4_5/dax 存在,容量与 CXL_MEM_SIZE 一致;
  • kernel.randomize_va_space=0
  • kernel.numa_balancing=0
  • vm.max_map_count 不小于 2097152

2. 运行小规模 PageRank

PageRank 不依赖外部数据集,适合用于检查完整运行链路:

cd bench/10-pagerank
make run-dt-mx-sc-f-debug GRAPH_SIZE=1000 NTHREADS=8

该目标会自动完成以下工作:

  1. 编译使用链接包装的 PageRank;
  2. 以 Debug 模式构建 libdthreads-mx-sc.so
  3. 清理系统页缓存;
  4. 通过 LD_PRELOAD 加载 xDSM-SC 运行时;
  5. 创建远端 worker,执行 200 轮 PageRank;
  6. 等待线程完成并回收运行时资源。

程序正常完成时会输出:

graph:  nodes
iter 1:  GB/s, dt=

上述小规模运行用于功能检查,不代表正式性能结果。

3. 运行演示规模 PageRank

仓库当前 PageRank Makefile 的默认参数为 44,000 个图节点和 32 个线程,矩阵工作集 约为 15.5 GB:

cd bench/10-pagerank
make run-dt-mx-sc-f-debug

该命令运行时间较长、输出较多,并要求共享后端和本地内存容量满足配置。首次验证 建议先使用前述 GRAPH_SIZE=1000 NTHREADS=8

完整环境准备

1. 定制内核与 /dev/ckpt

xDSM 的地址空间恢复和页面移动依赖 ckpt_mm。当前验证方式是将其以 CONFIG_CKPT_MM=y 编入定制 Linux 内核,而不是在运行时加载独立模块。

在已经集成 ckpt_mm 的内核源码目录中执行:

make -j"$(nproc)"
sudo make modules_install
sudo make install
sudo update-grub
sudo reboot

重启时从 GRUB 选择新内核,然后检查:

uname -r
grep CONFIG_CKPT_MM /boot/config-"$(uname -r)"
test -c /dev/ckpt && echo "ckpt device: ready"

仅编译本仓库的用户态代码不会创建 /dev/ckpt。内核源码的获取方式以及 ckpt_mm 与 Linux Kconfig/Makefile 的集成方法,应以比赛提交的定制内核仓库说明 为准。

2. 调整节点和共享内存配置

先查看目标机器拓扑:

lscpu -e=CPU,NODE
numactl --hardware

然后核对并按实际机器修改:

  • config/config.h 中的逻辑节点数量、CPU 亲和性和 NUMA 节点映射;
  • include/common.h 中的 CXL_MEM_SIZE
  • include/common.h 中的 MM_FILE_PATH

仓库当前配置使用四个逻辑计算节点,并将共享文件设置为:

/mnt/raminterleave4_5/dax

该路径对应实验服务器上的 CXL memory-only NUMA 节点 4、5,不能直接套用到其他 机器。

3. 创建共享内存后端

当前实验通过 tmpfs 在 CXL memory-only NUMA 节点上创建 64 GB 共享文件:

sudo ./scripts/numa/numa_memfile.sh create \
    -p interleave -n 4-5 -s 64G -f dax

ls -lh /mnt/raminterleave4_5/dax

该脚本会挂载 tmpfs、创建文件并预触碰页面,因此执行可能持续一段时间。节点编号、 容量和路径必须与目标机器拓扑及 include/common.h 保持一致。

仓库中的 scripts/dax/ 提供 DAX 后端配置参考,但本项目当前结果使用的是上述 CXL memory-only NUMA + tmpfs 配置。

4. 设置系统参数

echo 2097152 | sudo tee /proc/sys/vm/max_map_count
sudo sysctl -w kernel.randomize_va_space=0
echo 0 | sudo tee /proc/sys/kernel/numa_balancing

这些设置分别用于:

  • 提高可用 VMA 数量;
  • 关闭 ASLR,保持跨进程虚拟地址语义一致;
  • 关闭 AutoNUMA,避免内核自动迁移与 xDSM 页面放置相互干扰。

以上命令修改当前运行系统的内核参数。默认情况下重启后失效,不建议在未理解影响 时写入永久系统配置。

5. 编译运行时

在项目根目录执行:

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build \
    --target wrap dthreads-wise dthreads-xx-sc \
             dthreads-mx-sc dthreads-mx-rc-wt \
    -- -j"$(nproc)"

生成的共享库位于 build/lib/

配置 CMake 目标 共享库 benchmark 目标
CXL-only dthreads-wise libdthreads-wise.so run-dt-cxl-only
Local-only SC dthreads-xx-sc libdthreads-xx-sc.so run-dt-sc
xDSM-SC dthreads-mx-sc libdthreads-mx-sc.so run-dt-mx-sc-f
xDSM-RC dthreads-mx-rc-wt libdthreads-mx-rc-wt.so run-dt-mx-rc-f

各 benchmark 的 run-dt-* 目标会按指定配置重新构建运行库,因此也可以直接从 benchmark 目录启动。

运行不同配置

在相同图规模和线程数下检查四种配置:

cd bench/10-pagerank

make run-dt-cxl-only GRAPH_SIZE=1000 NTHREADS=8
make run-dt-sc       GRAPH_SIZE=1000 NTHREADS=8
make run-dt-mx-sc-f  GRAPH_SIZE=1000 NTHREADS=8
make run-dt-mx-rc-f  GRAPH_SIZE=1000 NTHREADS=8

公共 Makefile 会在每次运行前写入 /proc/sys/vm/drop_caches,因此这些目标需要 sudo 权限。小规模结果只用于检查各运行目标是否正常,正式比较应使用相同环境、 数据规模、线程数和重复运行方法。

其他应用

目录 应用或测试内容
bench/07-streamcluster 聚类与共享对象集合
bench/13-jacobi 规则数组迭代
bench/15-blackscholes 计算密集型负载
bench/24-loopnest 单节点读写热点
bench/27-bfs 图遍历与共享只读数据
bench/32-kv 哈希表、key/value 和并发访问
bench/33-graph500 CSR 图结构与不规则访问
bench/38-MOE MoE 权重和动态热点

这些目录通过 bench/Makefile.common 共享 xDSM 构建与运行规则。部分大型应用需要 额外数据集、模型权重或第三方源码,具体要求以各子目录的 README 为准。

常见问题

/dev/ckpt 不存在

检查当前内核是否包含:

grep CONFIG_CKPT_MM /boot/config-"$(uname -r)"

仅构建用户态运行库不能创建该设备。需要启动集成 ckpt_mm 的定制内核。

无法打开共享文件

检查:

ls -lh /mnt/raminterleave4_5/dax
grep -nE "MM_FILE_PATH|CXL_MEM_SIZE" include/common.h

共享文件路径和容量必须与编译期配置一致。

启动时出现固定地址映射失败

检查 ASLR 和 VMA 限制:

cat /proc/sys/kernel/randomize_va_space
cat /proc/sys/vm/max_map_count

当前原型依赖跨进程固定地址语义,地址布局冲突会导致初始化失败。

CPU 绑定或 NUMA 节点不存在

当前 config/config.h 保存的是实验服务器的拓扑。使用以下命令查看目标机器并重新 配置:

lscpu -e=CPU,NODE
numactl --hardware

动态页面放置日志或效果异常

动态页面放置依赖相应的硬件性能采样能力、内核性能事件支持和访问权限。程序能够 编译运行,不表示目标机器已经具备与实验服务器相同的采样条件。

当前边界

  • 当前 pthread 接口是兼容子集,不支持全部 POSIX pthread 语义;
  • pthread_join() 用于完成同步,不负责复制复杂业务返回值;
  • 复杂结果应由远端函数写入 xDSM 管理的共享结果对象;
  • 运行时回收 TID、thread args 和用户栈,业务对象由应用按照所有权约定释放;
  • 当前拓扑、CPU 绑定和共享文件路径采用编译期配置;
  • 当前原型尚未完成真实 CXL 3.0 多主机部署和 openEuler 实机验证;
  • 异常恢复、超时取消和节点失效处理仍需进一步工程化。

第三方代码与致谢

项目的部分基础数据结构和内存分配实现参考或使用了以下开源项目:

第三方代码、benchmark 和对照实现不应计入 xDSM 核心原创代码规模。具体许可证及 来源说明以最终提交仓库中的 LICENSE 和第三方声明文件为准。

关于
900.5 MB
邀请码
    Gitlink(确实开源)
  • 加入我们
  • 官网邮箱:gitlink@ccf.org.cn
  • QQ群
  • QQ群
  • 公众号
  • 公众号

版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9 京公网安备 11010802047560号