DeepEP 通信库使用指南(v2.1)
1.介绍
PPU DeepEP 是一款专为 PTG PPU 系列产品定制的通信库。它源自开源的 DeepSeek DeepEP,并针对 PPU 硬件架构进行了深度适配与优化。由于该库的 Python 与 C++ 编程接口(API)均有变更,因此上层计算框架需进行相应适配后方可使用。
1.1 适配现状以及使用说明
目前 PPU DeepEP 通信库只适用于 平头哥 PPU 相关产品系列,具体包括:
真武810E
单机内部 PPU 卡间仅支持自研通信协议 ICN Link
多机之间支持业界标准的 Mellanox CX6/CX7 RDMA 网卡
1.1.1 网卡 Affinity 设定
该配置在 DeepEP 版本 1.5.2 之后不需要额外设置,内部会自动检测 affinity 网卡并使用。
由于真武 810E PPU 和 NIC 并不是 1 比 1 配置,导致部分没有 PIX 网卡的 PPU 在使用网卡时会选择其他 NODE 关系的网卡,导致性能不佳, 对此我们调整为基于 nvml 映射关系的设定,目前是通过环境变量固化配置,后续会自动检测并绑定!如果是直接基于 Python buffer.py 开发和使用,可以不用感知此改动,若是适配 C++ 接口则当下需显式设置环境变量以达到理想性能。
if nvml_device_index // 4 == 0:
os.environ['NVSHMEM_HCA_LIST'] = 'mlx5_bond_4:1'
if nvml_device_index // 4 == 1:
os.environ['NVSHMEM_HCA_LIST'] = 'mlx5_bond_2:1'
if nvml_device_index // 4 == 2:
os.environ['NVSHMEM_HCA_LIST'] = 'mlx5_bond_3:1'
if nvml_device_index // 4 == 3:
os.environ['NVSHMEM_HCA_LIST'] = 'mlx5_bond_1:1'1.1.2 Native API 修改
原生 DeepEP 固定只支持机内 NUM_MAX_NVL_PEERS 个 Ranks 的通信规模,为了更加灵活的支持不同配置场景,我们在 Native (CPP) 层做了 API 的修改,新增了 local_ranks 的参数,用于表示机内参与通信的 PPU 数量,它可以是最大 16 PPUs 或者 8 PPUs。
Buffer(int rank, int local_ranks, int num_ranks, int64_t num_nvl_bytes, int64_t num_rdma_bytes, bool low_latency_mode, bool use_nvshmem_transport);Python 文件 buffer.py 里面自动检测机内规模大小,并传递给 Native Buffer 类,所以如果是基于 buffer.py 的使用,就不需要感知此改动。
1.1.3 功能增强以及扩展
功能名称 | 功能描述 | 支持版本 |
Hidden Size 扩展 | 支持 Hidden Size 2048 | 1.7 |
支持 Hidden Size 8192 | 1.7 | |
Intranode CUDA Graph | 支持 CUDA graph 模式下的 intranode kernel | 1.7 |
Load Balance 监控 | low latency dispatch 阶段,累计每个 Experts 的 token 总量,用户可以监控 Experts 的负载均衡情况 | 1.7 |
诊断功能 | 支持 low latency dispatch & combine 的等待时间检测,精准定位通信过程中的具体哪些 PPU 卡存在通信性能问题 | 1.7 |
UE8M0 数据格式支持 | 支持 low latency dispatch 阶段的 UE8M0 数据格式 | 1.7 |
支持 TopK 10 | 支持 low latency topk 10 的场景 | 2.0 |
支持用户自定义 timeout 时间 | 支持用户自定义 timeout 时间,防止 GeMM warmup 耗时长导致的超时 | 2.0 |
low latency dispatch & combine 量化支持 | low latency dispatch 支持 mxfp4 量化,low latency combine 支持 int8/fp8 量化 | 2.1 |
intranode & internode dispatch支持uint8类型scale | intranode & internode dispatch 支持 uint8 类型 scale 传输,以支持 mxfp4 量化场景 | 2.1 |
internode cuda graph 支持 | 支持 internode kernel cuda graph 模式 | 2.1 |
Hidden Size 扩展 | 支持 GLM & MiniMax 模型参数配置,hidden 3072 & 6144 | 2.1 |
Low Latency Combine SBO 支持 | 支持 Single Batch Overlap,配合 Gemm 做 Overlap 计算和通信功能 | 2.1 |
1.1.4 Python API 扩展
API 名称 | API 描述 | 支持版本 |
low_latency_dispatch | 新增 cumulative_local_expert_recv_stats 参数用于统计每个 Expert 累计的 token 数量,用于 load blance 的监控 | 1.7 |
low_latency_dispatch | 新增 round_scale 和 use_ue8m0 参数用于支持 dispatch 阶段的 UE8M0 数据格式 | 1.7 |
get_comm_stream | 获取 deepEP 当前通信的 Stream | 1.7 |
combine | 新增 bias Tensor,用于 Combine 阶段的 bias 累计操作 | 1.7 |
low_latency_dispatch | 新增参数 dispatch_wait_recv_cost_stats 用于统计从每个 Rank wait token 的时间 | 1.7 |
low_latency_combine | 新增参数 combine_wait_recv_cost_stats 用于统计从每个 Rank wait token 的时间 | 1.7 |
set_timeout_seconds | 设置 dispatch/combine 的 timeout 时间检查 | 2.0 |
low_latency_dispatch | 新增参数 use_mxfp4 用于支持 mxfp4 量化 | 2.1 |
low_latency_combine | 新增 Combine int8/fp8,以及 quant size 量化参数 | 2.1 |
internode_dispatch | 新增 num_worst_tokens 参数用于支持 cuda graph | 2.1 |
1.1.5 环境变量
环境变量名称 | 环境变量描述 | 支持版本 |
DEEPEP_DISABLE_NETWORK | 用于 ICN64 环境下,当网卡环境不 Ready 时,Disable 网络相关的初始化,确保只走 ICN Link 也可以正常工作。 | 2.1 |
DEEPEP_TIMEOUT_SECONDS | 在端到端场景下,Sglang 推理 warm up 阶段,Gemm 编译耗时很长,导致通信的 kernel wait 时间过长引起 默认 timeout crash,配置该参数可以确保超时时间足够长。 | 2.1 |
1.2 Internode Kernel
用户使用时可以用环境变量DEEPEP_INTERNODE_TRANSPORT_MODE 来指定不同的模式。目前支持以下两种模式,默认模式是 1。
DeepEP defined ibgda 模式:该模式使用 DeepEP 自定义的 ibgda path,性能更好,但在跑四机/八机的长 sequences 比如 16K 及以上时,压测仍会有 random hang 的问题,尚在定位。
使用方式:在每个node上配置环境变量。
export DEEPEP_INTERNODE_TRANSPORT_MODE=0。
native shmem ibrc 模式:默认模式,全部使用 shmem native api,走 ibrc 分支。两机情况下性能较好。
使用方式:在每个node上配置环境变量。
export DEEPEP_INTERNODE_TRANSPORT_MODE=1。
1.3 Low Latency Kernel
1.3.1 Int8 量化支持
从 1.6.0 开始 Low Latency Dispatch 支持 Int8 量化,对应的 API 也有所修改, 无论是 Python 还是 C++ 层面都新增了两个参数:
bool use_int8 :表示是否开启使用 Int8 量化。
int quant_size:表示 quant 的范围,目前支持 Group 和 Channel 模式:
Group 模式就是原生自带的 128 大小,以 128 为 Group 进行量化处理,此时 quant_size 等于 128。
Channel 模式就是以 token 为单位进行量化,此时 quant_size 为 hidden_size 大小。
从 2.1 版本开始,APIs 参数进一步扩展,支持 Dispatch mxfp4 量化,以及 Combine int8/fp8 量化。
low_latency_dispatch(const torch::Tensor& x, const torch::Tensor& topk_idx,
const std::optional<torch::Tensor>& cumulative_local_expert_recv_stats,
const std::optional<torch::Tensor>& dispatch_wait_recv_cost_stats,
int num_max_dispatch_tokens_per_rank, int num_experts,
bool use_fp8, bool round_scale, bool use_ue8m0, bool use_mxfp4,
bool async, bool return_recv_hook, bool use_int8, int quant_size);
low_latency_combine(const torch::Tensor& x, const torch::Tensor& topk_idx,
const torch::Tensor& topk_weights,
const torch::Tensor& src_info, const torch::Tensor& layout_range,
bool overlap, const std::optional<torch::Tensor>& packed_recv_count,
const std::optional<torch::Tensor>& comp_signal, int block_m, int threshold,
int num_sms, const std::optional<torch::Tensor>& combine_wait_recv_cost_stats,
int num_max_dispatch_tokens_per_rank, int num_experts,
bool zero_copy, bool async, bool return_recv_hook,
bool use_fp8, bool round_scale, bool use_int8, int quant_size,
const std::optional<torch::Tensor>& out = std::nullopt);def low_latency_dispatch(self, x: torch.Tensor, topk_idx: torch.Tensor,
num_max_dispatch_tokens_per_rank: int, num_experts: int,
cumulative_local_expert_recv_stats: Optional[torch.Tensor] = None,
dispatch_wait_recv_cost_stats: Optional[torch.Tensor] = None,
use_fp8: bool = False, round_scale: bool = False, use_ue8m0: bool = False, use_mxfp4: bool = False,
async_finish: bool = False, return_recv_hook: bool = False,
use_int8: bool = False, quant_size: int = 128)
def low_latency_combine(self, x: torch.Tensor, topk_idx: torch.Tensor, topk_weights: torch.Tensor,
handle: tuple, overlap: bool = False, packed_recv_count: torch.Tensor = None,
comp_signal: torch.Tensor = None, block_m: int = 64, threshold: int = 0,
num_sms: int = 3, zero_copy: bool = False, async_finish: bool = False,
return_recv_hook: bool = False, out: Optional[torch.Tensor] = None,
combine_wait_recv_cost_stats: Optional[torch.Tensor] = None,
use_fp8: bool = False, round_scale: bool = False,
use_int8: bool = False, quant_size: int = 128)1.3.2 默认 Enable ICN Link
从 1.6.0 版本开始,deepEP 默认打开 ICN Link,用户可以通过 allow_nvlink_for_low_latency_mode 修改设定。
def __init__(self, group: dist.ProcessGroup,
num_nvl_bytes: int = 0, num_rdma_bytes: int = 0,
low_latency_mode: bool = False, num_qps_per_rank: int = 12,
allow_nvlink_for_low_latency_mode: bool = True,
explicitly_destroy: bool = False)1.3.3 MXFP4 量化支持
从2.1.0开始,Low Latency Dispatch 支持 MXFP4 量化,对应的 API 也有所修改,无论是 python 还是 C++ 层面都新增了一个参数:
bool use_mxfp4:表示是否开启使用 MXFP4 量化,只支持quant_size为32。
1.4 开源框架调用说明
部分开源框架(例如vllm)调用DeepEP对外接口时,每个进程只能访问一张卡(cudaGetDeviceCount结果为1),这种情况下如果通过如下方式
deep_ep::Config::get_nvl_buffer_size_hint 来获取 num_nvl_bytes,以及使用 deep_ep::Config::get_rdma_buffer_size_hint 获取 num_rdma_bytes 作为Buffer的初始化参数,需要额外配置export DEEPEP_NUM_MAX_ICN_PEERS=num_local_ranks(单节点卡数)。
def get_buffer(group: dist.ProcessGroup, hidden_bytes: int) -> Buffer:
global _buffer
# NOTES: you may also replace `get_*_config` with your auto-tuned results via all the tests
num_nvl_bytes, num_rdma_bytes = 0, 0
for config in (Buffer.get_dispatch_config(group.size()), Buffer.get_combine_config(group.size())):
num_nvl_bytes = max(config.get_nvl_buffer_size_hint(hidden_bytes, group.size()), num_nvl_bytes)
num_rdma_bytes = max(config.get_rdma_buffer_size_hint(hidden_bytes, group.size()), num_rdma_bytes)
# Allocate a buffer if not existed or not enough buffer size
if _buffer is None or _buffer.group != group or _buffer.num_nvl_bytes < num_nvl_bytes or _buffer.num_rdma_bytes < num_rdma_bytes:
_buffer = Buffer(group, num_nvl_bytes, num_rdma_bytes)
return _buffer2.安装
2.1 whl 包安装
PPU DeepEP 通信库发布形式为 tar 压缩包,里面是 DeepEP whl 包。
参考下面指令便可以快速安装 DeepEP 通信库(以 1.5.2 版本为例,镜像为 pytorch:2.2-ubuntu22.04-cuda12.3-py310)。若需要下载其他版本的 DeepEP,可以提相关需求给到我们。
Note: 从 PPU SDK v1.5.2 release 开始,sailSHMEM 将随 SDK 一起发布,位置在 PPU_SDK/sailSHMEM 下,用户可以不用手动进行下载。
# 该地址为 1v5_release 最新版本的 DeepEP
wget http://ai-artifactory-pub.eng.t-head.cn:9000/artifactory/generic-local/PPU1.0/v1.5.2/Framework/DeepEP/DeepEP.tar.gz
# 1.5 版本之后,发布路径有变更, 具体如下:
wget https://art-pub.eng.t-head.cn/artifactory/generic-local/SAIL/v2.0.0/Framework/PyTorch/deep_ep-1.0.0-oe-cuda12.9-pytorch2.8.0-ubuntu2404-py312.tar.gzhttps://art-pub.eng.t-head.cn/artifactory/generic-local/SAIL/v2.0.0/Framework/PyTorch/deep_ep-1.0.0-oe-cuda12.9-pytorch2.8.0-ubuntu2404-py312.tar.gz
tar -xvf DeepEP.tar.gz
pip install deep_ep*.whl
# PPU_SDK 路径请根据环境实际情况配置
export LD_LIBRARY_PATH=/usr/local/PPU_SDK/sailSHMEM/lib:$LD_LIBRARY_PATH
export NVSHMEM_DIR=/usr/local/PPU_SDK/sailSHMEM从 2.1 Release 开始,DeepEP whl 包的发布会自带 sailSHMEM 相关依赖的 libs,所以不再需要单独配置 sailSHMEM 的路径。
2.2 源码安装
如果没有符合要求的 whl 包,DeepEP 也支持直接通过源码安装,具体步骤可以参考如下:
下载 DeepEP 源码。
git clone http://gitlab.alibaba-inc.com/ppu_open_source/DeepEP.git -b release配置 NVSHMEM_DIR 环境变量为 SDK 下的 sailSHMEM 路径。
# PPU_SDK 路径请根据环境实际情况配置 source /usr/local/PPU_SDK/envsetup.sh export LD_LIBRARY_PATH=/usr/local/PPU_SDK/sailSHMEM/lib:$LD_LIBRARY_PATH export NVSHMEM_DIR=/usr/local/PPU_SDK/sailSHMEM进入 DeepEP 源码目录进行编译安装。
cd DeepEP python setup.py build python setup.py install运行测试用例验证是否安装成功。
python tests/test_intranode.py python tests/test_low_latency.py
2.3 PiP 包编译和安装
1.6.0 之前,DeepEP 的编译和安装方式是以 egg 方式管理的,属于比较老的包安装管理方式,在实际测试中我们发现,容易和系统自带的 pip 安装方式冲突,无法覆盖系统现有版本,导致测试故障。
现在统一升级修改为 whl 包编译和安装方式,具体命令如下:
bash ./install.sh