大模型推理引擎 vLLM(28):custom_all_reduce 单机/跨节点原理(IPC、Fabric、HSA)

目录

[1 为什么有custom_all_reduce](#1 为什么有custom_all_reduce)

[2 节点内的Custom AllReduce](#2 节点内的Custom AllReduce)

[2.1 节点内的Custom AllReduce大体原理](#2.1 节点内的Custom AllReduce大体原理)

[2.2 IPC(HIP IPC)](#2.2 IPC(HIP IPC))

[3 跨节点的Custom AllReduce](#3 跨节点的Custom AllReduce)

[3.1 跨节点的Custom AllReduce大体原理](#3.1 跨节点的Custom AllReduce大体原理)

[3.2 Fabric(HSA RPC Fabric)](#3.2 Fabric(HSA RPC Fabric))

[4 那么IPC和跨机的Fabric通信区别在哪里](#4 那么IPC和跨机的Fabric通信区别在哪里)

[4.1 共同流程(IPC 和 Fabric 都一样)](#4.1 共同流程(IPC 和 Fabric 都一样))

[4.2 区别](#4.2 区别)

[4.3 IPC 模式:其实就是用了HIP API实现了共享显存的原理](#4.3 IPC 模式:其实就是用了HIP API实现了共享显存的原理)

[1. 分配显存](#1. 分配显存)

[2. 导出句柄(64 字节)](#2. 导出句柄(64 字节))

[3. 交换句柄(控制面)](#3. 交换句柄(控制面))

[4. 对端打开句柄](#4. 对端打开句柄)

[5. 限制](#5. 限制)

[4.4 Fabric 模式:其实就是用了hsa的api实现了共享显存](#4.4 Fabric 模式:其实就是用了hsa的api实现了共享显存)

[1. 分配显存](#1. 分配显存)

[2. 导出句柄(256 字节)](#2. 导出句柄(256 字节))

[3. 交换句柄(控制面)](#3. 交换句柄(控制面))

[4. 对端 attach 句柄](#4. 对端 attach 句柄)

[5. 能力](#5. 能力)

[4.5 区别对比表格](#4.5 区别对比表格)

[4.6 IPC 那套 API 属于谁?](#4.6 IPC 那套 API 属于谁?)

[4.7 Fabric 那套 API 属于谁?](#4.7 Fabric 那套 API 属于谁?)

[5 什么是HSA](#5 什么是HSA)

[HSA 是什么?](#HSA 是什么?)

[HSA Runtime 是什么?](#HSA Runtime 是什么?)

[和 HIP 是什么关系?](#和 HIP 是什么关系?)


abstract:

heterogeneous 英/ ˌhetərəˈdʒiːniəs / 有很多种类组成的;(化)不均一的,多相的;(数)不纯一的,参差的, 这里是异构的意思,

fabric 英/ ˈfæbrɪk / 布料,织物;构造,结构;(汽车的)车身,(飞机的)机身 这里是Fabric 在此指超节点 GPU 互联结构;跨节点 CAR 通过 HSA RPC Fabric API 完成显存导出与映射,而不是普通以太网/IB 发包。

一句话概括:Custom AllReduce 的快路径都是通过共享/映射 GPU 显存完成通信------节点内靠 HIP(或 CUDA)IPC 句柄,跨节点超节点靠 HSA Fabric 句柄;差别主要在用什么 API 导出和打开显存句柄。

HSA = Heterogeneous System Architecture(异构系统架构)

1 为什么有custom_all_reduce

Custom AllReduce 是 vLLM 为 Tensor Parallel 场景实现的一条专用 AllReduce 快路径。在满足条件时,它不经过 PyNccl/RCCL 这类通用集体通信,而是通过 vLLM 自研的 GPU 核函数(vllm._custom_ops),配合 GPU 显存 IPC/P2P 直连来完成求和;条件不满足时会自动回退到 NCCL/RCCL。

具体代码路径在 vllm/distributed/device_communicators/custom_all_reduce.py

2 节点内的Custom AllReduce

2.1 节点内的Custom AllReduce大体原理

  1. 控制面:用 torch.distributed(non-NCCL 的 cpu_group,一般是 Gloo)交换 IPC handle
  2. 数据面:用 vLLM 自研 C++ 扩展 vllm._custom_ops,通过 CUDA IPC / HIP IPC 让同机 GPU 直接访问彼此显存
  3. 计算:自定义 all-reduce kernel 在 GPU 上直接做 reduce

关键代码:

python 复制代码
def create_shared_buffer(...):
    pointer, handle = ops.allocate_shared_buffer_and_handle(size_in_bytes)
    ...
    dist.all_gather_object(handles, handle, group=group)  # 控制面:交换 handle
    ...
    pointers.append(ops.open_mem_handle(h))  # 数据面:打开对端显存

以及真正执行 reduce:

python 复制代码
ops.all_reduce(self._ptr, inp, out, 0, 0)  # 自定义 kernel,不是 torch

2.2 IPC(HIP IPC)

你的 GPU 显存 ──transport──> 别的 GPU 能直接读到这块显存 ──> kernel 做 reduce

项目 说明
全称 Inter-Process Communication,GPU 显存句柄共享
范围 同一台物理机(同一 OS、同一 shared-memory namespace)
原理 本机 GPU A 导出显存 handle(64 字节),GPU B 用 open_mem_handle 打开,直接访问 A 的显存
谁在用 vLLM 原版、aiter 同节点模式
限制 跨物理机不行------两台服务器之间没法用 IPC

IPC 确实是「进程间通信」

你没理解错。IPC = Inter-Process Communication(进程间通信)。

在 CAR 这里,它特指的是 GPU 显存的 IPC(HIP IPC / CUDA IPC),不是泛指 socket、MPI 那种通用进程通信:

进程 A(GPU0) 导出显存 handle

进程 B(GPU1) 打开 handle,直接访问 GPU0 的显存

所以:

  • 名字上:是进程间通信
  • 实现上:是 GPU 显存句柄共享 + 直连访问
  • 范围上:同一台物理机(同一 OS、同一 shared-memory namespace)

3 跨节点的Custom AllReduce

3.1 跨节点的Custom AllReduce大体原理

aiter 在同样思路上做了超节点扩展,数据面多了一条 Fabric 路径:

transport 数据面 适用场景
ipc HIP IPC(和 vLLM 类似) 同节点
fabric HSA RPC / Fabric 显存共享 跨节点超节点
auto 同节点 IPC,跨节点 Fabric 自动选择

aiter 初始化时会选 transport:

python 复制代码
if self.requested_transport == "ipc":
    if not same_node: return  # 跨节点不能用 IPC
    self.transport = "ipc"
elif self.requested_transport == "auto":
    self.transport = "ipc" if same_node else "fabric"
else:
    self.transport = "fabric"  # 强制超节点 Fabric

3.2 Fabric(HSA RPC Fabric)

项目 说明
范围 跨物理机(超节点:多台服务器通过专用互联)
原理 hsa_ext_rpc_memory_create/attach/detach 做跨节点显存导出和映射
handle 大小 256 字节(IPC 是 64 字节)
谁在用 aiter 超节点模式
前提 编译时 AITER_ENABLE_SUPERNODE_AR=1,运行时 AITER_AR_TRANSPORT=fabric

Fabric 也是「共享显存」思路,只是跨了物理机

可以这么理解:Fabric 把「导出显存 → 对端 attach → 直接访问」这套模型,从单机扩展到了跨节点。

aiter 文档里写得很直白:

层次 做什么
跨节点内存导出/映射 hsa_ext_rpc_memory_create/attach/detach
实际 AllReduce kernel 直接访问 Fabric 映射后的地址

4 那么IPC和跨机的Fabric通信区别在哪里

4.1 共同流程(IPC 和 Fabric 都一样)

  1. 每个 rank 在本机 GPU 上分配一块显存

  2. 每个 rank 把这块显存「导出」成一个 handle(句柄)

  3. 通过控制面把 handle 发给所有 rank(TCPStore / torch.distributed)

  4. 每个 rank 用对端 handle「打开/attach」,得到本进程里可访问的指针

  5. kernel 直接通过这些指针 读/写 远端显存,完成 all-reduce

4.2 区别

其实本质区别就在于:怎么把本机 GPU 显存「导出」成句柄,以及别的 rank 怎么「打开/attach」这个句柄,拿到可访问的地址。

其实往下看就能知道,它们两者相当于用了不同的api去实现了共享显存

4.3 IPC 模式:其实就是用了HIP API实现了共享显存的原理

1. 分配显存

hipMalloc / hipExtMallocWithFlags(...) // 本机 GPU 显存

2. 导出句柄(64 字节)

hipIpcGetMemHandle(&handle, gpu_ptr)

得到 hipIpcMemHandle_t(64 字节),描述「这块本机 GPU 显存」。

vLLM 里对应:

custom_all_reduce.cuLines 167-174

// Create IPC memhandle for the allocated buffer.

cudaIpcGetMemHandle((cudaIpcMemHandle_t*)handle.data_ptr(), buffer);

3. 交换句柄(控制面)

dist.all_gather_object(handles, handle, group=group) # vLLM

或 aiter 用 TCPStore pickle 交换

4. 对端打开句柄

hipIpcOpenMemHandle(&mapped_ptr, peer_handle, hipIpcMemLazyEnablePeerAccess)

在本进程地址空间里,映射到同一台机器上另一块 GPU 的显存。

5. 限制

  • 必须同一物理机(同一 OS、同一 shared-memory namespace)
  • 依赖 GPU P2P / XGMI
  • 跨物理机时 hipIpcOpenMemHandle 无效

4.4 Fabric 模式:其实就是用了hsa的api实现了共享显存

1. 分配显存

hipExtMallocWithFlags(..., hipDeviceMallocUncached) // 或 finegrained

要求这块显存可被 Fabric 导出。

2. 导出句柄(256 字节)

hsa_ext_rpc_memory_create(gpu_ptr, size, &fabric_handle)

得到 hsa_ext_rpc_memory_t(256 字节),不是 HIP IPC handle。

aiter 源码:

custom_all_reduce.cu Lines 404-425

python 复制代码
void get_meta_buffer_handle(..., transport) {
    if (transport == IPC)
        hipIpcGetMemHandle(...);           // 64 字节
    else
        hsa_ext_rpc_memory_create(...);  // 256 字节
}

3. 交换句柄(控制面)

和 IPC 同一套机制(aiter 的 _gather_ipc_meta,走 TCPStore),只是 handle 更大、内容不同。

4. 对端 attach 句柄

hsa_ext_rpc_memory_attach(&fabric_handle, 1, &fabric_agent, &mapped_ptr)

通过 HSA RPC Fabric agent,把远端物理机 GPU 显存映射到本机可访问地址。

aiter C++ 里:

custom_all_reduce.cuh Lines 2623-2646

python 复制代码
char* open_peer_handle(const void* handle) {
    if (transport == IPC)
        return open_ipc_handle(handle);      // hipIpcOpenMemHandle
    // Fabric:
    hsa_ext_rpc_memory_attach(&fabric_handle, 1, &fabric_agent_, &mapped_ptr);
    return mapped_ptr;
}

5. 能力

  • 可跨物理机(超节点专用互联)
  • 需要编译 AITER_ENABLE_SUPERNODE_AR=1
  • 需要链 libhsa-runtime64

4.5 区别对比表格

步骤 IPC Fabric
分配显存 hipMalloc / uncached uncached / finegrained
导出 API hipIpcGetMemHandle hsa_ext_rpc_memory_create
句柄类型 hipIpcMemHandle_t(64B) hsa_ext_rpc_memory_t(256B)
句柄交换 TCPStore / all_gather 一样
打开 API hipIpcOpenMemHandle hsa_ext_rpc_memory_attach
映射结果 同机另一 GPU 显存地址 跨机远端 GPU 显存地址
范围 单机 多机超节点

4.6 IPC 那套 API 属于谁?

属于 HIP(ROCm 运行时),不是 aiter 自己的 API。

API 所属库
hipMalloc / hipExtMallocWithFlags HIP Runtime(libamdhip64
hipIpcGetMemHandle HIP IPC API(仍在 HIP/ROCm 里)
hipIpcOpenMemHandle HIP IPC API

在 NVIDIA 上,vLLM 用的是同一思路的 CUDA Runtime API:

  • cudaMalloc
  • cudaIpcGetMemHandle
  • cudaIpcOpenMemHandle

4.7 Fabric 那套 API 属于谁?

不属于 aiter,属于 HSA Runtime(libhsa-runtime64) 的超节点扩展 API。

API 所属库
hsa_ext_rpc_memory_create HSA RPC Fabric 扩展
hsa_ext_rpc_memory_attach HSA RPC Fabric 扩展
hsa_ext_rpc_memory_detach HSA RPC Fabric 扩展
hsa_iterate_agents 标准 HSA Runtime

aiter 文档写得很清楚:跨节点内存导出/映射用的是 hsa_ext_rpc_memory_create/attach/detach,并且 .so 会链接 libhsa-runtime64

所以 Fabric API 是 AMD超节点平台(HSA + Fabric 互联) 提供的,不是 aiter 发明的。

5 什么是HSA

HSA 是什么?

HSA = Heterogeneous System Architecture(异构系统架构)

最初由 AMD 等推动的一套规范,目标是让 CPU 和 GPU(以及其它加速器)在同一套系统模型下协同工作,包括:

  • 统一的「设备/agent」抽象
  • 统一的内存与访问模型
  • 设备发现、队列、同步等运行时能力

可以把它看成:比 HIP 更底层的一整套「异构计算平台规范 + 运行时基础设施」。

HSA Runtime 是什么?

HSA Runtime 是 HSA 规范的具体实现库,在 Linux 上通常是:

libhsa-runtime64.so

它提供的是运行时 API,例如:

能力 典型 API
发现设备 hsa_iterate_agents(枚举 CPU、GPU 等 agent)
内存管理 各类 HSA 内存分配/映射 API
队列与同步 提交任务、信号量等
超节点扩展 hsa_ext_rpc_memory_create/attach/detach(Fabric 跨节点显存)

你们 aiter Fabric 模式里用的 hsa_ext_rpc_memory_*,就是 HSA Runtime 提供的扩展 API,不是 aiter 自己定义的。

和 HIP 是什么关系?

在 AMD/海光 ROCm 生态里,可以粗略看成两层:

你写 kernel、跑算子

HIP ← 类似 CUDA,日常开发主要用这个

HSA Runtime ← 更底层,管 agent、部分内存/互联能力

驱动 / 硬件

| HIP | HSA Runtime |
|-------|------------------------------|---------------------------------|
| 角色 | GPU 编程接口(写 kernel、malloc 显存) | 异构系统运行时(设备模型、底层互联) |
| 类比 | CUDA | 比 CUDA Driver 更「系统级」的一层 |
| 开发者 | 经常直接写 | 多数时候不直接写,库/驱动会调 |
| 在你们场景 | IPC 用 hipIpcGetMemHandle | Fabric 用 hsa_ext_rpc_memory_* |

所以:

  • IPC:走 HIP 自己的同机显存句柄机制
  • Fabric:跨机时 HIP IPC 不够,要借助 HSA Runtime 的 Fabric/RPC 内存扩展
相关推荐
一颗小树x3 天前
NVIDIA Jetson Thor 运行 LLM / VLM:模型全整理与 vLLM 实践
人工智能·llm·jetson·vllm
一个王同学3 天前
从零到一 | CV转多模态大模型 | week17 | LLM 推理优化 & vLLM 详解
人工智能·深度学习·算法·机器学习·计算机视觉·vllm
换个昵称23 天前
大模型学习8下-高性能推理引擎vLLM学习笔记
笔记·学习·vllm
Token炼金师3 天前
引擎四强:vLLM、SGLang、TensorRT-LLM 与 llama.cpp —— 推理引擎选型对决
人工智能·llm·llama·vllm·tensorrt-llm·sglang
武子康4 天前
调查研究-224 Prefill 与 Decode 分离:高并发 LLM Serving 的下一层架构
人工智能·ai·架构·llm·gpu·vllm·sglang
zhanghaofaowhrql5 天前
vLLM 与 SGLang 推理框架性能横评:架构、吞吐与延迟的深度解析
架构·vllm·sglang
高级打杂工程师-伍六六6 天前
【昇腾】本地 27B 编程模型接入 Claude Code 实战:Qwopus3.6-27B-Coder 在 vLLM-Ascend 上的部署与踩坑
昇腾·npu·vllm·claude code
聪明的一休丶7 天前
VLLM v0.24.0 版本深度解析:新引擎、新架构与大规模服务全家桶升级
python·架构·vllm
happyprince8 天前
21-vLLM 可观测性分析:Metrics & Monitoring
vllm