Skip to content

DeepEP

DeepEP is a GPU-resident expert-parallel dispatch backend. It uses GPU interconnects such as NVLink within a node and NVSHMEM/GPUDirect RDMA on supported multi-node deployments. Whether it outperforms the default alltoall path depends on the model, token shape, EP topology, fabric, and SM allocation.

  • Supported NVIDIA GPUs and an admitted intra-node or multi-node fabric
  • deep_ep wheel installed (see Installation)
  • ep_dispatch: deepep in model config
  • For internode (multi-node) EP: nvidia_peermem kernel module loaded and IBGDA enabled on all nodes (see below)
Terminal window
pip install deep_ep-*.whl # use a wheel compatible with the selected CUDA/PyTorch profile

Verify:

import deep_ep
print("DeepEP available")

For single-node EP (all GPUs on one machine), the wheel alone is sufficient. For multi-node EP, NVSHMEM handles inter-node RDMA communication and requires two additional steps on every node.

nvidia_peermem bridges the NVIDIA driver and the InfiniBand stack to enable GPUDirect RDMA. Without it, NVSHMEM cannot register GPU buffers with IB HCAs and DeepEP will crash at the first dispatch with SIGABRT and errors like:

WARN: device mlx5_0 cannot allocate buffer on the specified memory type. Skipping...

Load it on every node:

Terminal window
sudo modprobe nvidia_peermem

Verify:

Terminal window
lsmod | grep nvidia_peermem

To persist across reboots, add it to /etc/modules:

Terminal window
echo nvidia_peermem | sudo tee -a /etc/modules

IBGDA allows NVSHMEM to issue RDMA operations directly from GPU SM threads without CPU involvement. Add the following to /etc/modprobe.d/nvidia.conf on every node:

options nvidia NVreg_EnableStreamMemOPs=1 NVreg_RegistryDwords="PeerMappingOverride=1;"

Then rebuild the initramfs and reboot:

Terminal window
sudo update-initramfs -u
sudo reboot

Verify after reboot:

Terminal window
sudo cat /proc/driver/nvidia/params | grep -E "EnableStreamMemOPs|RegistryDwords"
# EnableStreamMemOPs: 1
# RegistryDwords: "PeerMappingOverride=1;"

Important: nvidia_peermem must be reloaded after every reboot (via /etc/modules or modprobe) — the IBGDA driver settings alone do not load it automatically.

model:
ep_dispatch: deepep
deepep_buffer_size_gb: 2.0 # communication buffer pool per GPU (default: 2.0)
deepep_num_sms: 20 # SMs dedicated to communication (default: 20)
deepep_async_combine: false # async combine overlap (experimental)
ParameterDefaultDescription
ep_dispatchalltoallSet to deepep to enable
deepep_buffer_size_gb2.0Per-GPU communication buffer pool in GB. Larger buffers can reduce chunking but consume more resident memory.
deepep_num_sms20SMs dedicated to communication kernels. Must be even.
deepep_async_combinefalseOverlap combine with next layer’s compute (experimental, currently disabled — see Async Combine)

The default path uses a device-side distributed AllToAll collective:

GPU 0 → collective send/receive buffers → GPU 1

DeepEP uses GPU-initiated transport and specialized dispatch/combine kernels:

GPU 0 → NVLink within a node, or NVSHMEM/GPUDirect RDMA across nodes → GPU 1

The ordinary XoRL AllToAll path does not stage token payloads through host memory. Compare the two backends on the intended topology rather than assuming a fixed latency multiplier.

Standard AllToAll (NCCL)GPU 0tokensNCCL buffersend bufferNCCL bufferrecv bufferGPU1NVLink (via NCCL)collective scheduledevice buffersmeasure this pathtarget shape + topologyGPU memory → NCCL staging buffer→ NVLink → NCCL recv buffer → GPU memorycollective-managed device data pathDeepEP (single-node view)GPU 0tokensGPU 1memoryNVLink RDMA (direct write)No CPU involvementGPU-initiated RDMAmeasure this pathsame shape + topologyGPU memory → NVLink → GPU memorySM kernels manage pipelining + flow controlspecialized GPU dispatch/combine path

DeepEP dedicates a fixed number of SMs to communication kernels. This creates a direct tradeoff between communication bandwidth and compute throughput:

deepep_num_smsCommunication bandwidthCompute SMs remainingBest for
8Smaller communication allocationMoreCandidate when expert compute dominates
20 (default)Default starting pointDefault starting pointInitial bring-up and measurement
32Larger communication allocationFewerCandidate when dispatch/combine dominates
48+High communication allocationFewerUse only after a shape-matched profile shows a benefit

deepep_num_sms must be even. Start with 20 and tune based on profiling — if XORL_DEBUG_EP=1 shows dispatch time > compute time, increase SMs; if compute time dominates, decrease.


The buffer is initialized lazily and shared across MoE layers. deepep_buffer_size_gb supplies the minimum NVLink allocation. For EP sizes supported by the installed DeepEP version, XoRL also asks DeepEP for dispatch and combine size hints and uses the maximum of those hints and the configured minimum. Older DeepEP versions or unrecognized EP sizes fall back to the configured value.

For an EP group spanning nodes, the implementation also allocates the RDMA buffer from DeepEP’s hints and rejects an NVLink allocation above DeepEP’s signed-int32 limit; keep deepep_buffer_size_gb <= 2.0 for that path. An initialization or dispatch allocation failure is a sizing error—XoRL does not implement the token-volume chunking formula previously shown here.


deepep_async_combine: true requests overlap of the combine communication (outputs flowing back from expert ranks) with the next layer’s compute:

Step N: dispatch → compute → [combine starts]
Step N+1: [combine finishes] + next layer compute (overlapped)

Benefit (when working): Hides combine latency behind useful compute, especially when combine > dispatch (typical for large output projections).

Limitations:

  • Gated off behind XORL_DEEPEP_UNSAFE_ASYNC_COMBINE=1
  • Requires careful ordering of CUDA streams
  • Not compatible with pipeline parallelism (PP > 1)

ScenarioRecommendation
Bring-up, portability, or missing DeepEP/NVSHMEM prerequisitesStart with alltoall
DeepEP prerequisites pass and dispatch/combine dominates a shape-matched profileBenchmark DeepEP with the same model, batch, sequence, EP placement, and fabric
Multi-node deploymentValidate nvidia_peermem, IBGDA, HCA reachability, and NVSHMEM before comparing throughput
Async combineKeep disabled unless the downstream stream-ordering contract has been independently validated

deep_ep not found:

AttributeError: module 'deep_ep' has no attribute 'Buffer'

Install a DeepEP wheel matching the selected CUDA, PyTorch, GPU, and fabric environment.

SIGABRT / num_recv_tokens: -1 on all ranks:

WARN: device mlx5_0 cannot allocate buffer on the specified memory type. Skipping...
Global rank: 0, num_recv_tokens: -1, num_rdma_recv_tokens: -1

nvidia_peermem is not loaded. Run sudo modprobe nvidia_peermem on all nodes. See Cluster Prerequisites.

init failed for transport: IBGDA: IBGDA driver settings are not active. Check that NVreg_EnableStreamMemOPs=1 and PeerMappingOverride=1 are set in /etc/modprobe.d/nvidia.conf, then run sudo update-initramfs -u and reboot. Verify with:

Terminal window
sudo cat /proc/driver/nvidia/params | grep EnableStreamMemOPs

Buffer initialization OOM: Reduce deepep_buffer_size_gb. Check available GPU memory before the EP buffer allocation.

SM contention (low compute throughput): Reduce deepep_num_sms to 8–12. Use XORL_DEBUG_EP=1 to print per-phase timing:

Terminal window
XORL_DEBUG_EP=1 torchrun ... -m xorl.cli.train config.yaml

Shape mismatch errors during backward: With the default gradient_checkpointing_method: recompute_full_layer, R3 routing replay is used automatically to reuse the recorded expert assignments when AllToAll is recomputed. If you see shape mismatches, verify routing replay is enabled. Using recompute_before_dispatch or no_recompute avoids AllToAll recomputation and does not require local forward/backward route replay. See MoE Routing Replay.

No fallback to AllToAll: If DeepEP fails to initialize, xorl does not fall back automatically. Set ep_dispatch: alltoall explicitly.


FileDescription
src/xorl/distributed/moe/deepep.pyDeepEP buffer lifecycle, dispatch/combine autograd boundaries, and internode preflight
src/xorl/models/layers/moe/moe_block.pyMoEBlock — DeepEP dispatch/combine integration, async combine stream management
src/xorl/models/layers/moe/experts.pyMoEExperts._ep_forward() — DeepEP dispatch, compute, combine phases; XORL_DEBUG_EP timing