- 人工智能
- 大模型
- 模型推理服务
- 后端
【免费下载链接】Mooncake
Mooncake is the serving platform for Kimi, a leading LLM service provided by Moonshot AI.
导读
本文面向希望在鲲鹏 950(Kunpeng 950)平台上为 Mooncake 启用 UB(Unified Bus,统一总线)传输能力的开发者,完整介绍基于 URMA(Unified Remote Memory Access)与 OBMM(Ownership Based Memory Management)两种 UB 协议实现的 Kunpeng UB Transport:从新增依赖、CMake 构建开关、注册验证,到单节点/多设备基准测试与源码级原理剖析。读完本文,你将能够独立在 openEuler 24.03(LTS-SP3)上编译出带ub协议支持的 Mooncake,并在真实或 Mock URMA 设备上运行传输引擎基准测试与单元测试。
一、背景:UB 协议与 URMA / OBMM
Kunpeng UB Transport 的源码位于mooncake-transfer-engine/src/transport/kunpeng_transport(源码目录实际命名为kunpeng_transport),内部包含针对 UB 协议的 Transport 对接代码与实现逻辑,相关实现细节可对照 ub_transport.cpp 与 ub_transport.h。
UB(Unified Bus,统一总线)是与 RDMA、CXL、NVLink 和 TCP 处于同一抽象层的传输协议,属于可在应用层灵活选择的一类传输方案。目前 UB 协议有两个开源实现:
- URMA(Unified Remote Memory Access,统一远程内存访问):UB 协议为上层应用提供的统一编程抽象与核心语义层。它基于 UB 协议低延迟、高带宽的底层特性,为远程共享内存的访问与操作提供统一的 API 和语义接口。URMA 的开源项目为 openEuler 社区的 UMDK。
- OBMM(Ownership Based Memory Management):面向超节点环境的内核内存管理系统,支持跨节点的物理内存共享。系统通过内核模块(
obmm.ko)和用户态库(libobmm.so)提供高效的远程内存访问能力。OBMM 的开源项目为 openEuler 社区的 obmm。
在 Mooncake 的代码中,这两种端点类型被定义为枚举UB_ENDPOINT_TYPE { URMA_ENDPOINT = 0, OBMM_ENDPOINT = 1 }(见 ub_transport.h),UbTransport构造函数默认采用URMA_ENDPOINT。
二、新增依赖与前置条件
Kunpeng UbTransport 在 Mooncake 本身依赖的基础上,新增了部分 URMA 和 OBMM 相关依赖,要点如下:
| 依赖类别 | 要求 |
|---|---|
| 硬件平台 | 支持原生 UB 互联架构的鲲鹏 950 CPU |
| OS 版本 | openEuler 24.03(LTS-SP3) |
| URMA 依赖 | UMDK:yum install umdk-urma-devel,或从 UMDK 源码构建安装 |
| 协议优势 | URMA 提供类似 RDMA 的内存语义,并针对鲲鹏芯片片上互联进行了专门优化 |
URMA 的 UMDK 安装方式有两种等价路径:
# 方式一:yum 直接安装开发包 yum install umdk-urma-devel # 方式二:从源码构建 git clone https://atomgit.com/openeuler/umdk.git cd umdk mkdir build && cd build cmake .. make -j$(nproc) sudo make install构建 Mooncake 本体所需的常规编译依赖(CMake、glog、jsoncpp、numa、gtest、pybind11 等)与此前一致。另外,仓库通过 FindUrma.cmake 自动探测系统是否已安装 UMDK:优先在/usr/include、/usr/local/include及其子路径下查找urma_api.h,并在/usr/lib、/usr/lib64等路径下查找liburma.so;若系统未安装,则会通过 FetchContent 拉取 UMDK 源码(仅提供头文件),此时真实的 UB 后端在运行期不可用,测试环境会注入自己的适配层。
三、构建与编译
3.1 前置条件
- openEuler 24.03(LTS-SP3)操作系统;
- 已安装 UMDK:
yum install umdk-urma-devel,或已从源码构建安装(满足urma_api.h头文件与liburma.so库可用即可)。
3.2 CMake 配置与编译
# 克隆 Mooncake 仓库并初始化子模块 git clone https://github.com/kvcache-ai/Mooncake.git cd Mooncake git submodule update --init --recursive # 启用 UB 传输层进行配置 mkdir build && cd build cmake .. -DUSE_UB=ON \ -DURMA_INCLUDE_DIR=/usr/include \ -DURMA_LIBRARY=/usr/lib64/liburma.so \ -DCMAKE_BUILD_TYPE=RelWithDebInfo # 编译 make -j$(nproc)编译选项说明:
-DUSE_UB=ON:总开关。在 src/transport/CMakeLists.txt 中,只有USE_UB为 ON 时才会把kunpeng_transport子目录编入并链接ub_transport对象库;-DURMA_INCLUDE_DIR:URMA 头文件目录,默认探测值为/usr/include;-DURMA_LIBRARY:liburma.so的完整路径。该值会被 kunpeng_transport/CMakeLists.txt 读取:若找到真实库,则编译ub_transport时链接真实 URMA 库;若未找到,则编译时加入urma/mock_urma.cpp(Mock 实现),用于无真实硬件环境下的测试,CMake 会打印Not Found liburma.so building ub_transport with Mock URMA library警告。
3.3 验证 UB 传输层注册
# 检查 UB 传输层是否已注册 ./mooncake_server --list-transports # 预期输出: rdma, tcp, nvlink, ubUbTransport::getName()返回字符串"ub"(见 ub_transport.h),因此它会在传输层列表中以上述名字呈现。
3.4 Python 侧验证(可选)
构建完 Python 绑定后,也可以用 TransferEngine 直接初始化ub协议:
from mooncake.engine import TransferEngine te = TransferEngine() result = te.initialize('127.0.0.1', 'P2PHANDSHAKE', 'ub', '') print(f'Initialize result: {result}') # 预期为 0初始化成功后日志应包含类似内容:
URMA module init success found 1 devices. device_name : urma0 EID : 01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10四、源码视角:UbTransport 的组成与工作流程
4.1 类层次与核心组件
UB 传输层的源码设计围绕三个层次展开(对应 urma_endpoint.h 中的类定义):
| 组件 | 职责 |
|---|---|
UbTransport | 传输层主类,负责管理 URMA 资源与端点、内存注册、提交传输、查询状态 |
UbContext(子类UrmaContext) | 每个设备一个上下文,负责设备打开、上下文/JFC/JFR 等资源创建与销毁、内存区注册、事件轮询 |
UbEndPoint(子类UrmaEndpoint) | 每个远端连接一个端点,负责 jetty(URMA 通信队列)创建、握手建连、实际的数据收发 |
从源码结构看,URMA 侧的实体对象对应关系为:
urma_context:URMA 设备上下文句柄;urma_jfce(Jetty Factory for Completion Events):完成事件队列,UrmaContext::construct中按num_jfce_per_ctx创建;urma_jfc(Jetty Factory for Completion,发送完成队列):num_jfc_per_ctx个,每个深度为max_jfc_e(默认 4096);urma_jfr(接收队列):num_jfc_per_ctx个,深度 2048,传输模式URMA_TM_RC;urma_jetty:通信 jetty,每个端点按num_jetty_per_ep(默认 1)创建,采用 Reliable Connection(RC)模式。
4.2 安装(install)流程
UbTransport::install()(见 ub_transport.cpp)是传输层初始化的入口,依次完成:
- 保存元数据(
TransferMetadata)与本地拓扑(Topology)引用; initializeUbResources():调用init()初始化 URMA 模块(urma_init),从拓扑中获取 HCA 设备列表;若拓扑为空则回退到mock_urma_device用于测试;逐个设备构建UrmaContext并调用doConstruct,失败的设备会被disableDevice禁用;若无任何可用设备则返回ERR_DEVICE_NOT_FOUND;allocateLocalSegmentID():以"ub"为协议名创建本地 SegmentDesc 并登记每个设备的名称与 EID;startHandshakeDaemon():启动握手守护进程,注册onSetupConnections回调,用于被动接收远端建连请求;updateLocalSegmentDesc():把本地段描述发布到元数据服务。
4.3 内存注册与数据通路
- 注册:
registerLocalMemory()对每个 context 调用registerMemoryRegion()与buildLocalBufferDesc()。URMA 实现(urma_endpoint.cpp)通过urma_register_seg注册内存段,访问权限为URMA_ACCESS_READ | URMA_ACCESS_WRITE | URMA_ACCESS_ATOMIC,Token 策略为URMA_TOKEN_NONE;注册长度受max_seg_size(默认0x10000000000,即 1 TiB)约束。当注册名称为kWildcardLocation("*")时,会自动通过getMemoryLocation探测内存位置并写入 BufferDesc; - 提交:
submitTransfer()把批量请求挂到 BatchDesc 上,submitTransferTask()按slice_size将请求切分为 Slice,为每个 Slice 选择设备(selectDevice,按 buffer 地址范围与拓扑亲和性选择),最终经submitPostSend下发到对应 context 的 worker 池; - 完成:worker 通过
urma_poll_jfc轮询发送完成队列(JFC),成功的 Slice 调用markSuccess(),失败(含URMA_CR_WR_FLUSH_ERR)的 Slice 交回上层做重试或失败处理(urma_endpoint.cpp)。
五、运行与测试
5.1 单节点基准测试
利用mooncake-transfer-engine/example下的transfer_engine_bench(其命令行参数定义见 transfer_engine_bench.cpp):
# 终端 1:目标端(Target) ./transfer_engine_bench \ --mode=target \ --protocol=ub \ --device_name=urma0 \ --local_server_name=127.0.0.1 \ --metadata_server=P2PHANDSHAKE # 终端 2:发起端(Initiator) ./transfer_engine_bench \ --mode=initiator \ --protocol=ub \ --device_name=urma0 \ --metadata_server=P2PHANDSHAKE \ --segment_size=8388608 \ --batch_size=1 \ --segment_id=127.0.0.1:$PORT参数含义:
--mode:运行模式,initiator或target(发起端负责读写远端段,目标端被动等待);--protocol=ub:选择 UB 传输协议。bench 程序中--protocol=ub分支会先通过拓扑discover({FLAGS_device_name})发现设备,再以空参安装ub传输层(见 transfer_engine_bench.cpp);--device_name=urma0:指定 URMA 设备名;urma0,urma1,...逗号分隔即可启用多设备;--metadata_server=P2PHANDSHAKE:元数据服务地址;P2PHANDSHAKE表示点对点握手模式(无需 etcd),也可使用etcd://...、redis://...等格式;--segment_size=8388608:发起端申请的段大小(8 MiB);--batch_size:每批传输任务数;--segment_id=127.0.0.1:$PORT:目标段标识,$PORT需替换为目标端实际监听端口。
5.2 多设备基准测试
自动发现多个 URMA 设备:
./transfer_engine_bench \ --protocol=ub \ --device_name=urma0,urma1,urma2,urma3多个设备名逗号分隔后,会生成对应的 CPU/NIC 拓扑 JSON(包含多个 device 的亲和矩阵),使传输引擎能够按拓扑选择最优设备。
5.3 单元测试
UB 传输层单测位于 ub_transport_test.cpp,构建后运行:
./build/mooncake-transfer-engine/tests/ub_transport_test测试套件包含两个核心用例:
| 测试 | 描述 |
|---|---|
MultiWrite | 多次(10 轮)写入操作,每次 4 MB 数据,校验提交与完成状态机 |
MultipleRead | 多次读写操作并做数据完整性校验 |
也可用 CTest 一次性运行全部单测:
cd build && ctest --output-on-failure单测相关的环境变量:
export MC_METADATA_SERVER=P2PHANDSHAKE # 默认值 export MC_LOCAL_SERVER_NAME=127.0.0.1:12345 # 默认值需要注意的是,单测在没有真实 URMA 硬件时会走 Mock 路径:URMA_LIBRARY未找到时 CMake 会编译urma/mock_urma.cpp(见 kunpeng_transport/CMakeLists.txt),且拓扑为空时initializeUbResources会回退到mock_urma_device,保证无硬件环境也能验证传输层逻辑。
六、UB 相关配置参数
UB 传输层在 config.h 中定义了一组专属调优参数:
| 参数 | 默认值 | 说明 |
|---|---|---|
num_jfc_per_ctx | 2 | 每个 context 的发送完成队列(JFC)数量 |
num_jfce_per_ctx | 2 | 每个 context 的完成事件队列(JFCE)数量 |
eid_index | 0 | 设备 EID 索引(多 EID 设备时选择使用哪个 EID) |
max_seg_size | 0x10000000000 | 单个内存段注册的最大长度(1 TiB) |
max_jfc_e | 4096 | JFC 队列深度(URMA 侧当前使用该默认值) |
num_jetty_per_ep | 1 | 每个端点的 jetty(通信队列)数量 |
其中num_jfc_per_ctx与num_jfce_per_ctx可通过环境变量MC_NUM_CQ_PER_CTX同时覆盖(见 config.cpp);eid_index在 urma_endpoint.cpp 的openDevice中决定从设备 EID 列表中选择哪个 EID 创建 context,若该 EID 对应的 GID 为空,日志会提示 "GID is NULL, please check your EID index"。另外,updateUrmaGlobalConfig会根据设备实际能力自动下调max_ep_per_ctx与num_jfc_per_ctx,避免超出硬件容量(urma_endpoint.h)。
七、常见问题排查
| 现象 | 排查方法 |
|---|---|
UbTransport: No URMA devices found | 确认 URMA 已正确安装且设备可见:ls /usr/lib64/liburma.so、检查头文件urma_api.h是否存在,用urma_admin -l查看设备列表 |
URMA module init failed | 确认 URMA 内核模块已加载:sudo modprobe urma,用sudo lsmod \| grep urma检查模块状态,用urma_admin -l查看设备状态 |
Device urma0 port not active | 确认 UB 端口已配置并激活:urma_admin -p urma0 |
cannot find -lurma | 确认liburma.so已安装且在库路径中:export LD_LIBRARY_PATH=/usr/lib64:$LD_LIBRARY_PATH |
结语
Kunpeng UB Transport 为 Mooncake 在鲲鹏 950 CPU 平台上提供了一套与 RDMA 同层、针对片上互联优化的高速传输方案:URMA 语义层负责远程内存访问的统一抽象,OBMM 面向超节点内存共享场景,二者都以UbTransport这一统一接口接入 Mooncake 传输引擎。通过本文的构建开关、验证命令、基准测试与源码级剖析,开发者可以快速在 openEuler 24.03 + 鲲鹏 950 环境中启用ub协议,并借助 Mock URMA 在无硬件环境下先行验证传输层逻辑;后续可依据MC_NUM_CQ_PER_CTX等参数与设备能力进行调优,以适配大规模参数传输与分布式训练等场景。
- 人工智能
- 大模型
- 模型推理服务
- 后端
【免费下载链接】Mooncake
Mooncake is the serving platform for Kimi, a leading LLM service provided by Moonshot AI.
相关推荐
Mooncake 鲲鹏 UB 传输(Kunpeng UB Transport)接入指南:基于 URMA 的 Unified Bus 构建、配置与验证
Mooncake 鲲鹏 UB 传输(Kunpeng UB Transport)接入指南:基于 URMA 的 Unified Bus 构建、配置与验证 本文面向在
人工智能大模型模型推理服务后端Mooncake FlagCX 传输(Transport)接入指南:构建、启用与 tebench 连通性验证
Mooncake FlagCX 传输(Transport)接入指南:构建、启用与 tebench 连通性验证 本篇技术指南围绕 Mooncake 开源仓库中 d
人工智能大模型模型推理服务后端Mooncake EFA Transport 实战指南:基于 AWS EFA 与 libfabric 构建高速传输引擎
Mooncake EFA Transport 实战指南:基于 AWS EFA 与 libfabric 构建高速传输引擎 导读 本文聚焦 Mooncake 项目中
人工智能大模型模型推理服务后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考