目录

1 为什么有custom_all_reduce

2 节点内的Custom AllReduce

2.1 节点内的Custom AllReduce大体原理

2.2 IPC(HIP IPC)

3 跨节点的Custom AllReduce

3.1 跨节点的Custom AllReduce大体原理

3.2 Fabric(HSA RPC Fabric)

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

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

4.2 区别

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

1. 分配显存

2. 导出句柄(64 字节)

3. 交换句柄(控制面)

4. 对端打开句柄

5. 限制

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

1. 分配显存

2. 导出句柄(256 字节)

3. 交换句柄(控制面)

4. 对端 attach 句柄

5. 能力

4.5 区别对比表格

4.6 IPC 那套 API 属于谁?

4.7 Fabric 那套 API 属于谁?

5 什么是HSA

HSA 是什么?

HSA Runtime 是什么?

和 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

关键代码:

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:

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:

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

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

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 内存扩展

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐