Files
wehub-resource-sync d7e28c34cf
Code Format Check / format-check (push) Has been cancelled
docs: make Chinese README the default
2026-07-13 10:14:38 +00:00

456 lines
20 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- WEHUB_ZH_README -->
> [!NOTE]
> 本文档由 WeHub 基于上游 README 翻译整理,属于社区翻译,非官方中文文档。
> [English](./README.en.md) · [原始项目](https://github.com/deepseek-ai/DeepEP) · [上游 README](https://github.com/deepseek-ai/DeepEP/blob/HEAD/README.md)
> 原作者、版权与许可证归属以原始项目及本仓库 LICENSE 文件为准。
# DeepEP
DeepEP (DeepEveryParallel) 是一款面向现代机器学习训练与推理的高性能通信库。该库目前聚焦于专家并行(Expert Parallelism,EP)——提供高吞吐、低延迟的全对全(all-to-allGPU 内核(MoE dispatch 与 combine),并支持包括 FP8 在内的低精度;同时也提供面向流水线并行(Pipeline ParallelismPP)、上下文并行(Context ParallelismCP)以及远程内存访问(Engram)的实验性原语,均设计为占用零或极少量 SM。所有内核均通过轻量级即时编译(Just-In-Time,JIT)模块在运行时编译,安装时无需进行 CUDA 编译。
尽管设计轻量,DeepEP 的性能在各种配置下均可达到或超过硬件带宽上限。
## News
- **V2 发布**:对 Expert Parallelism 进行了完整重构——相较 V1 以数倍更少的 SM 资源实现极致性能,同时支持显著更大的 scale-up 与 scale-out 域。V2 也已从 NVSHMEM 后端切换为更轻量的 **NCCL Gin 后端**
### New features
- **Fully JIT**Just-In-Time 编译)
- **NCCL Gin backend**
- Header-only & lightweight
- Able to reuse existing NCCL communicators
- **EPv2**
- 高吞吐与低延迟 API 统一为单一 `ElasticBuffer` 接口,并采用新的 GEMM layout
- 支持更大的 scale-up 与 scale-out 域(最高 EP2048
- 解析式 SM 与 QP 数量计算——不再需要自动调优
- hybrid 与 direct 模式均继续支持
- 对于类 V3 的传统训练,SM 占用从 24 降至 4 - 6,同时保持相当或更优的性能
- **0 SM Engram**with RDMA
- **0 SM PP**with RDMA
- **0 SM CP**with Copy Engine
### Notes
- Buffer 大小占用大于 V1
- 不再支持 0 SM RDMA 低延迟 EP
- Engram、PP 与 CP 为实验性功能
### Still on-going features
- **Elastic GPU & CPU buffers**:连续的虚拟地址空间,底层映射到 GPU 与 CPU 物理内存的混合体,从而实现全自动、透明的 Engram 或不均衡 EP
- 通过利用 EP replay 处理负载不均衡,以减小中间 buffer 大小
- 面向 DP 与 TP 的 all-gather 更新与 reduce-scatter 实现
有关传统 V1 文档(基于 NVSHMEM),请参阅 [docs/legacy.md](docs/legacy.md)。
## Performance
按照 V3 的配置,我们以每 batch 8K tokens、7168 隐藏维度、top 8 experts、FP8 dispatching 与 BF16 combining 进行测试,得到如下结果:
| Arch | NIC type | Topo | Dispatch Bottleneck Bandwidth | Combine Bottleneck Bandwidth | #SMs |
|--|--|--|--|--|--|
| SM90 | CX7 | EP 8 x 2 | 90 GB/s (RDMA) | 81 GB/s (RDMA) | 12 |
| SM90 | CX7 | EP 8 x 4 | 61 GB/s (RDMA) | 61 GB/s (RDMA) | 6 |
| SM100 | CX7 | EP 8 x 2 | 90 GB/s (RDMA) | 91 GB/s (RDMA) | 12 |
| SM100 | N/A | EP 8 | 726 GB/s (NVLink) | 740 GB/s (NVLink) | 64 (Max perf) |
| SM100 | N/A | EP 8 | 643 GB/s (NVLink) | 675 GB/s (NVLink) | 24 (Min #SM) |
说明:结果为逻辑带宽。例如,在 `EP 8 x 2` 情形下,90 GB/s 实际包含本地 rank 流量。
与 V1 相比,**V2 峰值性能最高可达 1.3 倍,同时最多可节省 4 倍 SM 数量**。
我们暂时省略更大 EP 配置的结果,但鼓励感兴趣的用户自行 benchmark。根据我们的内部经验,我们预期内核在规模扩展时仍将持续饱和硬件带宽。
V1 性能数据请参阅 [docs/legacy.md](docs/legacy.md#performance)。
## Quick start
### Requirements
- Hopper (SM90) GPU,或其他支持 SM90 PTX ISA 的架构
- Python 3.8 及以上
- CUDA version
- SM90 GPU 需 CUDA 12.3 及以上
- PyTorch 2.10 及以上
- NCCL 2.30.4 及以上
- 节点内通信需 NVLink
- 节点间通信需 RDMA 网络
### Install NCCL dependency
我们建议使用 pip 安装 NCCL,以便 DeepEP 能在 Python 环境中自动定位它。可使用以下命令安装:
```bash
pip install "nvidia-nccl-cu13>=2.30.4" --no-deps
```
### Install NVSHMEM dependency
DeepEP 也依赖 NVSHMEM 以支持传统方法。请参阅我们的 [NVSHMEM Installation Guide](docs/nvshmem.md) 获取说明。
### Development
```bash
# Build and make symbolic links for SO files
python setup.py build
# You may modify the specific SO names according to your own platform
ln -s build/lib.linux-x86_64-cpython-38/deep_ep_cpp.cpython-38-x86_64-linux-gnu.so
# Run test cases
# NOTES: you may modify the `init_dist` function in `tests/utils/envs.py`
# according to your own cluster settings, and launch into multiple nodes
python tests/elastic/test_ep.py
python tests/elastic/test_agrs.py
python tests/elastic/test_engram.py
python tests/elastic/test_pp.py
```
### Installation
```bash
python setup.py install
```
然后,在你的 Python 项目中 import `deep_ep`,即可开始使用!
## Interfaces and examples
### Buffer initialization
在 V2 中,所有 EP 操作——高吞吐与低延迟——均统一在单一 `ElasticBuffer` 接口下。可通过直接指定 MoE 设置来初始化 buffer,最优 SM 与 QP 数量将以解析方式计算。
```python
import torch
import torch.distributed as dist
from typing import Optional
from deep_ep import ElasticBuffer
# Communication buffer (will allocate at runtime)
_buffer: Optional[ElasticBuffer] = None
# Number of SMs to use for communication kernels (will be set at buffer creation)
_num_comm_sms: int = 0
def get_buffer(group: dist.ProcessGroup,
num_max_tokens_per_rank: int,
hidden: int,
num_topk: int,
num_experts: int,
use_fp8_dispatch: bool = False) -> ElasticBuffer:
"""Initialize or retrieve the ElasticBuffer for EP communication."""
global _buffer, _num_comm_sms
# Check if we can reuse the existing buffer
required_bytes = ElasticBuffer.get_buffer_size_hint(
group, num_max_tokens_per_rank, hidden,
num_topk=num_topk, use_fp8_dispatch=use_fp8_dispatch,
)
if _buffer is not None and _buffer.group == group and _buffer.num_bytes >= required_bytes:
return _buffer
# Allocate a new buffer with MoE settings
# NOTES: V2 buffer size consumption is larger than V1
_buffer = ElasticBuffer(
group,
num_max_tokens_per_rank=num_max_tokens_per_rank,
hidden=hidden,
num_topk=num_topk,
use_fp8_dispatch=use_fp8_dispatch,
)
# V2 analytically calculates the optimal SM count — no more auto-tuning needed
# You may also specify `num_sms` manually in dispatch/combine calls to override
_num_comm_sms = _buffer.get_theoretical_num_sms(num_experts, num_topk)
return _buffer
```
### Example use in model training or inference prefilling
V2 将 dispatch 与 combine API 统一为单一 `ElasticBuffer` 接口。以下示例展示如何在训练(含反向传播)或推理 prefilling 中使用它们。
```python
import torch
import torch.distributed as dist
from typing import Tuple, Union
from deep_ep import ElasticBuffer, EPHandle, EventOverlap
def dispatch_forward(x: Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]],
topk_idx: torch.Tensor, topk_weights: torch.Tensor,
num_experts: int,
num_max_tokens_per_rank: int,
expert_alignment: int = 1) -> \
Tuple[Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]],
torch.Tensor, torch.Tensor, EPHandle, EventOverlap]:
"""
MoE dispatch: route tokens to the corresponding experts across all ranks.
Supports both BF16 and FP8 (x as a tuple of [data, scale_factors]) inputs.
"""
global _buffer, _num_comm_sms
recv_x, recv_topk_idx, recv_topk_weights, handle, event = _buffer.dispatch(
x,
topk_idx=topk_idx,
topk_weights=topk_weights,
num_experts=num_experts,
num_max_tokens_per_rank=num_max_tokens_per_rank,
expert_alignment=expert_alignment,
num_sms=_num_comm_sms,
async_with_compute_stream=True,
)
# `handle` contains routing metadata for the subsequent combine call
# `handle.num_recv_tokens_per_expert_list` provides per-expert token counts for GEMM
# Use `event.current_stream_wait()` to synchronize the compute stream before using results
return recv_x, recv_topk_idx, recv_topk_weights, handle, event
def dispatch_backward(grad_recv_x: torch.Tensor,
grad_recv_topk_weights: torch.Tensor,
handle: EPHandle) -> Tuple[torch.Tensor, torch.Tensor, EventOverlap]:
"""The backward pass of MoE dispatch is actually a combine."""
global _buffer, _num_comm_sms
combined_grad_x, combined_grad_topk_weights, event = _buffer.combine(
grad_recv_x,
handle=handle,
topk_weights=grad_recv_topk_weights,
num_sms=_num_comm_sms,
async_with_compute_stream=True,
)
return combined_grad_x, combined_grad_topk_weights, event
def combine_forward(x: torch.Tensor,
handle: EPHandle) -> Tuple[torch.Tensor, EventOverlap]:
"""MoE combine: reduce expert outputs back to their original ranks."""
global _buffer, _num_comm_sms
combined_x, _, event = _buffer.combine(
x,
handle=handle,
num_sms=_num_comm_sms,
async_with_compute_stream=True,
)
return combined_x, event
def combine_backward(grad_combined_x: Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]],
handle: EPHandle) -> \
Tuple[Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]], EventOverlap]:
"""The backward pass of MoE combine is actually a dispatch."""
global _buffer, _num_comm_sms
grad_x, _, _, _, event = _buffer.dispatch(
grad_combined_x,
handle=handle,
num_sms=_num_comm_sms,
async_with_compute_stream=True,
)
return grad_x, event
```
为实现通信-计算重叠(communication-computation overlap),请使用 `EventOverlap` 接口来管理通信流与计算流之间的依赖关系:
```python
# After dispatch, overlap computation while communication is in-flight
recv_x, recv_topk_idx, recv_topk_weights, handle, event = dispatch_forward(...)
# ... do some independent computation here ...
# Wait for communication to finish before using results
event.current_stream_wait()
# Now safe to use recv_x, recv_topk_idx, recv_topk_weights
```
### 推理解码中的示例用法
在推理解码中,同样使用 `ElasticBuffer`。handle-caching 模式可在门控决策保持不变时跨迭代复用路由元数据,从而避免冗余的 CPU 同步。
```python
import torch
from typing import Tuple, Optional, Union
from deep_ep import ElasticBuffer, EPHandle, EventOverlap
def decode_dispatch(x: Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]],
topk_idx: torch.Tensor, topk_weights: torch.Tensor,
num_experts: int,
num_max_tokens_per_rank: int,
cached_handle: Optional[EPHandle] = None) -> \
Tuple[Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]],
torch.Tensor, torch.Tensor, EPHandle, EventOverlap]:
"""
MoE dispatch for inference decoding.
If `cached_handle` is provided, the layout is reused without CPU synchronization.
"""
global _buffer, _num_comm_sms
if cached_handle is not None:
# Reuse cached handle: skip layout recomputation and CPU sync
recv_x, _, _, handle, event = _buffer.dispatch(
x,
handle=cached_handle,
num_sms=_num_comm_sms,
async_with_compute_stream=True,
)
return recv_x, cached_handle.topk_idx, None, handle, event
recv_x, recv_topk_idx, recv_topk_weights, handle, event = _buffer.dispatch(
x,
topk_idx=topk_idx,
topk_weights=topk_weights,
num_experts=num_experts,
num_max_tokens_per_rank=num_max_tokens_per_rank,
num_sms=_num_comm_sms,
async_with_compute_stream=True,
)
return recv_x, recv_topk_idx, recv_topk_weights, handle, event
def decode_combine(x: torch.Tensor,
handle: EPHandle) -> Tuple[torch.Tensor, EventOverlap]:
"""MoE combine for inference decoding."""
global _buffer, _num_comm_sms
combined_x, _, event = _buffer.combine(
x,
handle=handle,
num_sms=_num_comm_sms,
async_with_compute_stream=True,
)
return combined_x, event
```
### 环境变量
本库提供了一些可能有用的环境变量:
- 通用
- `EP_BUFFER_DEBUG`: `0``1`,打印缓冲区初始化、SM 近似与后端调试信息,默认 `0`
- `EP_SUPPRESS_NCCL_CHECK`: `0``1`,抑制 NCCL 版本不匹配检查,默认 `0`
- `EP_AVOID_RECORD_STREAM`: `0``1`,避免对输出张量执行 `record_stream`,默认 `0`
- `EP_NUM_TOPK_IDX_BITS`: 整数,覆盖 top-k 索引编码的比特数,默认 `0`auto
- 网络
- `EP_NIC_NAME`: 字符串,用于查询网卡属性的默认网卡名称,默认 `mlx5_0`
- `EP_OVERRIDE_RDMA_SL`: 整数,覆盖用于流量隔离的 RDMA 服务等级索引
- `EP_DISABLE_GIN`: `0``1`,禁用 NCCL Gin 后端(回退到非 Gin 路径),默认 `0`
- JIT
- `EP_JIT_DEBUG`: `0``1`,打印 JIT 调试信息,默认 `0`
- `EP_JIT_CACHE_DIR`: 字符串,已编译内核的缓存目录,默认 `$HOME/.deep_ep`
- `EP_JIT_NVCC_COMPILER`: 字符串,NVCC 编译器路径;默认为 `torch.utils.cpp_extension.CUDA_HOME`
- `EP_JIT_CPP_STANDARD`: 整数,C++ 标准版本,默认 `20`
- `EP_JIT_PRINT_COMPILER_COMMAND`: `0``1`,打印编译命令,默认 `0`
- `EP_JIT_PTXAS_VERBOSE`: `0``1`,显示详细的 PTXAS 输出,默认 `0`
- `EP_JIT_PTXAS_CHECK`: `0``1`,断言已编译内核不使用本地内存,默认 `0`
- `EP_JIT_WITH_LINEINFO`: `0``1`,为性能分析工具嵌入源码行信息,默认 `0`
- `EP_JIT_DUMP_ASM`: `0``1`,同时转储 PTX 与 SASS,默认 `0`
- `EP_JIT_DUMP_PTX`: `0``1`,转储 PTX 输出,默认 `0`
- `EP_JIT_DUMP_SASS`: `0``1`,转储 SASS 输出,默认 `0`
- 调试与性能分析
- `EP_GIN_GDAKI_DEBUG`: `0``1`,启用 NCCL Gin GDAKI 调试输出,默认 `0`
- `EP_USE_NVIDIA_TOOLS`: `0``1`,在外部 NVIDIA 工具下运行时跳过内部性能分析,默认 `0`
- `EP_DISABLE_BARRIER_PROFILING`: `0``1`,在基准测试中禁用基于 barrier 的通信性能分析,默认 `0`
- 构建
- `EP_NCCL_ROOT_DIR`: 字符串,NCCL 安装目录路径;若未设置,则从 Python 环境自动检测
- `EP_NVSHMEM_ROOT_DIR`: 字符串,NVSHMEM 安装目录路径;若未设置,则从 Python 环境自动检测
- `TORCH_CUDA_ARCH_LIST`: 字符串,目标 CUDA 架构列表,例如 `"9.0"`
- `DISABLE_SM90_FEATURES`: `0``1`,为旧版方法禁用 SM90 特性,默认 `0`
- `DISABLE_AGGRESSIVE_PTX_INSTRS`: `0``1`,在旧版方法中禁用激进的 load/store 指令,默认 `0`
部分环境变量是**持久化的**:它们在构建时被捕获,并作为默认值写入已安装的包中。在导入时,除非被当前环境变量覆盖,否则会自动应用这些默认值。持久化变量包括:`EP_JIT_CACHE_DIR``EP_JIT_PRINT_COMPILER_COMMAND``EP_NUM_TOPK_IDX_BITS``EP_NCCL_ROOT_DIR`
更多细节请参阅[测试代码](tests/elastic/test_ep.py),或查阅相应的 Python 文档。
## 网络配置
DeepEP 已在 InfiniBand 网络上完成充分测试。不过,理论上它也兼容融合以太网上的 RDMARDMA over Converged EthernetRoCE)。
### 流量隔离
InfiniBand 通过虚拟通道(Virtual Lanes,VL)支持流量隔离。
为避免不同类型流量之间的相互干扰,我们建议按以下方式将工作负载划分到不同的虚拟通道:
- 专家并行(expert-parallel)工作负载
- 其他工作负载
对于 DeepEP V2,可通过设置 `sl_idx` 参数或 `EP_OVERRIDE_RDMA_SL` 环境变量来控制虚拟通道分配。
### 自适应路由
自适应路由(adaptive routing)是 InfiniBand 交换机提供的高级路由特性,可将流量均匀分布到多条路径上。尽管自适应路由会引入额外延迟,我们仍建议在所有网络负载条件下启用它。
### 拥塞控制
拥塞控制已禁用,因为它会损害最大带宽。若在某些场景下拥塞不可避免,我们建议将这些工作负载分配到低优先级虚拟通道。
### PCI 原子模式
若硬件支持,建议使用以下命令设置网卡的 `PCI_ATOMIC_MODE`,以提升 RDMA 原子操作性能:
```bash
sudo mlxconfig -y -d mlx5_$i set PCI_ATOMIC_MODE=4
```
## 实验分支
- [Zero-copy](https://github.com/deepseek-ai/DeepEP/pull/453)
- 消除 PyTorch 张量与通信缓冲区之间的拷贝,可显著降低常规模核的 SM 占用
- 该 PR 由**腾讯网络平台部(Tencent Network Platform Department**编写
- [Eager](https://github.com/deepseek-ai/DeepEP/pull/437)
- 使用低延迟协议可消除 RDMA 原子操作(atomic OPs)引入的额外 RTT 延迟
- [Hybrid-EP](https://github.com/deepseek-ai/DeepEP/tree/hybrid-ep)
- 基于 TMA 指令的新后端实现,实现最小 SM 占用并支持更大的 NVLink 域
- 针对单批次场景的细粒度通信-计算重叠
- 为非 NVLink 环境提供 PCIe 内核支持
- 支持 NVFP4 数据类型
- [AntGroup-Opt](https://github.com/deepseek-ai/DeepEP/tree/antgroup-opt)
- 该优化系列由**蚂蚁集团网络平台部(AntGroup Network Platform Department**编写
- [Normal-SMFree](https://github.com/deepseek-ai/DeepEP/pull/347) 通过将通信内核执行与 NIC token 传输解耦,从 RDMA 路径中消除 SM 占用,从而释放 SM 用于计算
- [LL-SBO](https://github.com/deepseek-ai/DeepEP/pull/483) 通过信令机制将 Down GEMM 计算与 Combine Send 通信重叠,以降低端到端延迟
- [LL-Layered](https://github.com/deepseek-ai/DeepEP/pull/500) 使用 rail 优化转发与数据合并优化跨节点 LL 算子通信,以降低延迟
- [Mori-EP](https://github.com/deepseek-ai/DeepEP/tree/mori-ep)
- 基于 [MORI](https://github.com/ROCm/mori) 后端(低延迟模式)的 ROCm/AMD GPU 支持
- [nvDev](https://github.com/deepseek-ai/DeepEP/tree/nvDev)
- 基于 V2 的分支,集成最新 CUDA 特性,例如 Compute Fabric TransportCFT),可在较小 token 规模下带来更优延迟。
## 社区分支
- [uccl/uccl-ep](https://github.com/uccl-project/uccl/tree/main/ep) - 支持在异构 GPU(如 Nvidia、AMD)和 NIC(如 EFA、Broadcom、CX7)上运行 DeepEP
- [Infrawaves/DeepEP_ibrc_dual-ports_multiQP](https://github.com/Infrawaves/DeepEP_ibrc_dual-ports_multiQP) - 在 IBRC 传输中添加多 QPQueue Pair)方案及双端口 NIC 支持
- [antgroup/DeepXTrace](https://github.com/antgroup/DeepXTrace) - 用于高效、精确定位慢 rank 的诊断分析工具
- [ROCm/mori](https://github.com/ROCm/mori) - AMD 面向性能关键型 AI 工作负载(如 Wide EP、KVCache transfer、Collectives)的下一代通信库
## 致谢
DeepEP V2 基于 [NCCL](https://github.com/nvidia/nccl) Gin backend 构建。感谢 @sjeaugey@pakmarkthub@sb17v@xiaofanl-nvidia 以及 NCCL 团队的支持!
## 许可证
本代码仓库在 [the MIT License](LICENSE) 下发布。
## 引用
```bibtex
@misc{deepep2025,
title={DeepEP: an efficient expert-parallel communication library},
author={Chenggang Zhao and Shangyan Zhou and Liyue Zhang and Chengqi Deng and Zhean Xu and Yuxuan Liu and Kuai Yu and Jiashi Li and Liang Zhao},
year={2025},
publisher = {GitHub},
howpublished = {\url{https://github.com/deepseek-ai/DeepEP}},
}
```