The rest of this guide covers DeepEP-V2 (the NCCL-GIN / ElasticBuffer path).
This section covers the other DeepEP backend — V1, the legacy NVSHMEM backend
(deep_ep.Buffer, low_latency_dispatch), built on source-compiled NVSHMEM linked
against EFA's libfabric. It is what vLLM drives via --all2all-backend deepep_high_throughput /
deepep_low_latency. We ran a fresh head-to-head on p5en / H200 / 16 EFA NICs: our
NVSHMEM 3.6.5 fork vs the AWS 3.7.0 build.
| V1 — NVSHMEM backend (this section) | V2 — NCCL-GIN backend (rest of site) | |
|---|---|---|
| Python object | deep_ep.Buffer / low_latency_dispatch | deep_ep.ElasticBuffer |
| Transport | NVSHMEM → CPU proxy → libfabric/EFA | NCCL-GIN type-2 CPU proxy → EFA |
| vLLM flag | --all2all-backend deepep_high_throughput | deepep_low_latency | --all2all-backend deepep_v2 |
| Needs on EFA | source-built NVSHMEM vs EFA libfabric + the EFA shim (no IBGDA) | aws-ofi-nccl GIN plugin + ElasticBuffer |
| DeepEP commit class | 567632d (pre-EPv2) | EPv2 (restructured kernels) |
Both are CPU-proxy paths on EFA. Neither uses GPU-initiated RDMA — EFA exposes no IBGDA. The "proxy tax" §2 describes applies to V1 too.
All four capstones are complete. The same NVSHMEM/EFA transport validated across serving (vLLM + SGLang), training (Megatron), and full RL (NeMo-RL GRPO):
| capstone | framework | workload | headline result |
|---|---|---|---|
| C1 | vLLM v0.11.1 (source) | EP16 serving, both backends | eager verdict revised: graphed LL wins decode (61.6-65.0 ms, 1.06-1.08× dense), HT unchanged |
| C2 | SGLang 0.5.5.post3 (stock) | EP16 serving, 3 deepep-modes | INVERTS C1: LL wins everywhere, 60–66 ms TPOT, decode c32 497.6 tok/s (+50%) |
| C3 | Megatron-LM 23dd639c (stock, 0 patches) | 2-node MoE training | loss 26.41→24.59; grad-norms match V2 digit-for-digit; EFA TX 1.083 GB |
| C4 | NeMo-RL 46be4e8 | full GRPO e2e (rollout→reward→train→refit) | 3/3 steps, internode EP4, EFA TX 537 GB/node |
| metric | A — ours (NVSHMEM 3.6.5 + SWAP) | B — AWS (NVSHMEM 3.7.0 + patch) | winner |
|---|---|---|---|
| dispatch | 37.0 / 37.0 | 71.6 / 71.7 | B 1.94× |
| combine | 30.6 / 30.7 | 63.1 / 63.5 | B 2.08× |
| FP8 dispatch | 29.0 | 62.6 | B 2.13× |
| correctness | 24/24 | 64/64 | tie |
Both stacks are CPU-proxy + libfabric. AWS pulls ahead purely on host-transport efficiency it gets from NVSHMEM 3.7.0:
fi_send atomic.Our SWAP-004/007/009/017/018 patches are partial hand-ports of work NVSHMEM 3.7.0 ships natively and
more completely. The fix is to rebase off 3.6.5 onto 3.7.0 + adopt the AWS deepep_aws_efa.patch,
not to keep patching 3.6.5.
vLLM's deepep_low_latency backend calls Buffer.low_latency_dispatch/combine. On
our NVSHMEM 3.6.5 build this segfaulted on H200 (signal 11 @ 0x28). Root
cause (verified at source + runtime, not an SRD-ordering or NIC-count issue — reproduced at
NIC_PER_PE=1):
get_transport_mem_handle returns a NULL/garbage remote handle at high offset →
NULL flows into fi_write (nvshmemt_libfabric_rma_impl); the NDEBUG
build compiled out the guarding assert. Size-gated, not H200-gated.
| path | 3.6.5 fix attempt | result |
|---|---|---|
| LL dispatch | NVSHMEM_ENABLE_RAIL_OPT=1 | WORKS — 0.66/0.67/0.72 ms, PASS (first ever our-LL on H200) |
| LL combine | RAIL_OPT + CUMEM_GRANULARITY=2GB | still segv (offset ~939 MB) — needs the real fix |
| both | rebase to NVSHMEM 3.7.0 | fixed upstream — see below |
The real fix is NVSHMEM 3.7.0: its changelog explicitly closes this — "Fixed a bug in remote
transports during memory registration … memory handle management cache" + a NVSHMEM_CUMEM_GRANULARITY
static-heap override. The AWS V1 build already runs full LL D+C on H200 (~0.82 ms) because its patch deletes
the device-side rkey cache, so all handle resolution happens CPU-side in 3.7.0's fixed transport — the device
never executes the buggy offset >> log2_granularity.
The microbench above says AWS V1 moves dispatch bytes ~2× faster. The real question is whether that
converts to serving throughput. We built a single NGC-from-scratch image (NVSHMEM 3.7.0 + DeepEP
567632d + the EFA shim + vLLM from source) and served Qwen3-30B-A3B-FP8 with Expert
Parallelism (EP16, DP16×TP1) across 2× p5en/H200, driving both DeepEP-V1 backends. Repro =
one Dockerfile + one serve.yaml + one run_test.sh:
github.com/dmvevents/deepep-efa-ab-h200/tree/master/capstone.
| regime | HT TPOT | LL TPOT | LL vs HT | HT tok/s | LL tok/s |
|---|---|---|---|---|---|
| prefill conc4 | 73.5 | 98.4 | +34% worse | 53.0 | 37.0 |
| prefill conc32 | 77.0 | 134.8 | +75% worse | 386.8 | 190.8 |
| decode conc4 | 72.7 | 93.8 | +29% worse | 55.0 | 42.6 |
| decode conc32 | 75.2 | 98.2 | +31% worse | 424.9 | 324.9 |
The original matrix above ran both backends --enforce-eager because NGC triton lacks
triton_key. We retested with -O.level=0 -O.cudagraph_mode=FULL (level-0
compilation never touches inductor, so no triton_key; CUDA graphs capture fully). LL improves
21-38% TPOT; HT is unchanged (within 1.4% — it was never eager-limited).
| regime | dense (eager) TPOT / toks | HT graphed | LL graphed | LL/dense toks |
|---|---|---|---|---|
| prefill c4 | 65.3 / 58.8 | 72.5 / 53.5 | 77.9 / 45.6 | 0.78× |
| decode c4 | 66.5 / 59.6 | 71.8 / 55.4 | 61.6 / 64.6 | 1.08× |
| prefill c32 | 70.2 / 420.9 | 77.6 / 373.6 | 83.4 / 188.8 | 0.45× |
| decode c32 | 68.5 / 462.7 | 74.9 / 425.1 | 65.0 / 488.7 | 1.06× |
Evidence: dmvevents/deepep-efa-ab-h200 commit 55c322a, capstone/results/{cudagraph-retest,dense-ab}/. Retest 2026-07-08. Dense arm run under eager (no cudagraph, matching the V2 campaign's dense-arm methodology).
LL-worse-on-vLLM was an eager artifact. Cuda-graphed LL beats HT in decode (-13/-14%), loses prefill (+7/8%): mode-per-phase, as the SGLang lane predicted. Frameworks CONVERGE once dispatch is cuda-graphed: vLLM LL decode c32 65.0 ms / 488.7 tok/s vs SGLang LL 64.3 / 497.6 — the ~60-65 ms floor is the transport, not the framework.
First measured DeepEP-beats-dense serving cells on EFA in either campaign (graphed LL 1.06-1.08× decode throughput) — but dense wins prefill decisively and remains the safe single-mode default. The site's capacity-not-speedup verdict STANDS overall; this adds a measured decode-heavy exception, not a reversal.
The 2× microbench win does NOT convert to serving. HT per-user TPOT is pinned at ~73–77 ms across every regime (p99 within 1 ms of p50 in decode). Aggregate throughput scales with concurrency, but per-token latency is a hard floor — the fixed CPU-proxy all-to-all round-trip (§2's proxy tax). A faster dispatch microbench moves bytes faster; it does not remove the per-token host hop.
"Low-latency" is not low-latency on EFA. deepep_low_latency is 29–75% worse TPOT
than deepep_high_throughput in every regime, including its design home (small-batch
decode: 93.8 vs 72.7 ms). On EFA's CPU-proxy path its smaller-message / put+signal optimizations are
swamped by — and add overhead to — the per-token host round-trip. Use deepep_high_throughput.
This reproduces the V2 capstone's verdict (0.65–0.97× dense): a serving speedup needs GPU-initiated
transport (GDAKI/IBGDA), which no shipping EFA stack exposes. Update 2026-07-17: a native kernel-posted path (CQ-poll, no hardware counters) is now measured in §10 — it beats the proxy on dispatch/combine latency but remains a research path, not a serving recipe; this section's verdict is unchanged.
Same image lineage, same NVSHMEM 3.7.0 + EFA shim, same model and nodes — but served by
SGLang 0.5.5.post3 (--moe-a2a-backend deepep, TP16 + DP-attention 16). We swept all
three --deepep-mode values across the same 4 regimes. On vLLM, "low-latency" was 29–75%
worse. On SGLang, low_latency wins every regime:
| regime | normal | low_latency | LL vs normal |
|---|---|---|---|
| prefill conc4 | 92.1 / 41.5 | 61.2 / 62.6 | -34% TPOT |
| prefill conc32 | 99.2 / 306.8 | 66.3 / 445.8 | -33% TPOT, +45% tok/s |
| decode conc4 | 91.1 / 43.8 | 60.4 / 65.8 | -34% TPOT |
| decode conc32 | 96.4 / 330.9 | 64.3 / 497.6 | -33% TPOT, +50% tok/s |
auto mode == normal within noise (auto routes prefill chunks through the normal path).
Raw JSONL + logs: capstone/sglang/results/ in the repro repo.
Why the inversion? SGLang's LL mode captures cuda graphs around
low_latency_dispatch and keeps the CPU proxy hot; its normal mode force-disables
cuda-graph, so per-token Python/launch overhead dominates. vLLM v0.11.0 ran
--enforce-eager in both backends, so its LL path only added per-message overhead
on the proxy (this was subsequently confirmed and resolved — see the REVISED eager-confound block in
the Capstone-1 section above). Which DeepEP mode to use is a framework-integration property (cuda-graph coverage
of the dispatch path), not a transport property.
Does this change the site's verdict? It moves the floor, not the direction. The ~75 ms "proxy floor" from the vLLM lane is not a transport constant — cuda-graphed LL pushes it to ~60–66 ms. But per-token latency still plateaus far above IB-class DeepEP deployments, and no dense-vs-DeepEP A/B was run on SGLang here: this is a better operating point within the same capacity/fit verdict, not evidence of a serving speedup over dense. GPU-initiated transport (GDAKI/IBGDA) remains the lever that would change the direction.
Does V1 train? The vLLM/SGLang capstones validated serving; this validates training. Stock
Megatron-LM @23dd639c is a native DeepEP-V1 consumer: megatron/core/transformer/moe/fused_a2a.py
imports deep_ep.Buffer directly with zero patches (the V2 campaign's Megatron PR #4632 exists to
steer this file away from V1 — so for V1, upstream-as-is is the recipe). We ran the V2 lane's
Gate-5 "Shape Y" driver (Qwen3-30B-A3B-style MoE: 128 experts, top-8, hidden 2048) on 2× p5en/H200 with
the same seeds and base commit → direct A/B of Buffer/NVSHMEM-proxy vs
ElasticBuffer/NCCL-GIN as a training transport.
| step | V1 loss (this section) | V2 loss (Gate-5) | V1 grad_norm | V2 grad_norm |
|---|---|---|---|---|
| 1 | 26.4062 | 26.4075 | 30.6430 | 30.6430 |
| 2 | 25.1106 | 25.1026 | 28.1979 | 28.1979 |
| 3 | 24.5944 | 24.6097 | 27.0909 | 27.0909 |
Losses agree to ~3 decimals (bf16 reduction-order noise); grad-norms match digit-for-digit.
NVSHMEM v3.7.0 banner, NVSHMEM_REMOTE_TRANSPORT=libfabric, provider efa.
Evidence: github.com/dmvevents/deepep-efa-ab-h200/tree/master/capstone/megatron.
The verdict: numerical equivalence across transports. Grad-norms match V2 digit-for-digit and losses agree to ~3 decimal places — the same tokens move through two entirely different transports (NVSHMEM host-proxy vs NCCL-GIN) with interchangeable training math. This is the strongest correctness statement either lane has produced.
Caveats: Only NORMAL-mode dispatch/combine is on Megatron's path (never
low_latency_*). Step-time comparison vs V2 is not valid (different GPUs H200 vs H100,
different warmup) — this validates correctness and fit, not a training-throughput claim. It does not
change this site's capacity-not-speedup verdict; it confirms V1 trains with the same math as V2.
Does V1 train with reinforcement learning? The vLLM/SGLang capstones validated inference
serving; Capstone-3 validated supervised training. This validates the complete GRPO loop
(rollout generation → reward → training → weight refit) — the stack V2's Gate-6 explicitly skipped
as "too heavyweight". Stock NeMo-RL @46be4e8 drove 3 complete GRPO steps on
Qwen3-30B-A3B across 2× p5en/H200, using vLLM colocated rollout generation (32 MATH completions
per step, mean ~927 tokens), reward calculation, GRPO policy training through stock Megatron
fused_a2a.py (deep_ep.Buffer → NVSHMEM 3.7.0 → EFA), and ZMQ weight
refit back into vLLM (3.4 s per step).
| step | Loss | Avg Reward | step time (s) |
|---|---|---|---|
| 1/3 | 0.0003 | 0.1875 | 63.1 |
| 2/3 | 0.0459 | 0.0625 | 85.4 |
| 3/3 | 0.0232 | 0.5312 | 98.1 |
Timing split (step 3): generation 62%, policy training 8%, refit 4%. Rollouts are
real — 32 completions/step, logged with rewards/advantages/logprobs. Source:
github.com/dmvevents/deepep-efa-ab-h200/tree/master/capstone/nemo-rl (commit bc930e7).
The verdict: every stage of the RL loop executes coherently over V1. The expert-parallel
a2a genuinely crossed nodes (TP4/PP1/EP4 topology, verified with EFA hardware TX counters at 537 GB/node).
Megatron policy training routed through stock fused_a2a.py (deep_ep.Buffer),
and weight streaming back to vLLM's generation engine completed in 3.4 s per step.
Honest caveats: 3 steps × 8 prompts is a transport-validation shape, not a convergence claim — reward numbers at n=32 samples/step are high-variance noise (0.19 → 0.06 → 0.53 is sampling variance, not learning progress). GRPO loss is near zero by construction at this scale. What this run does prove: the full loop (rollout + reward + training + refit) works end-to-end on V1.
The PP2 gotcha: an earlier PP2/EP2 run "passed" identically, but its PP boundary aligned with the node boundary → EP groups landed intranode, so DeepEP never touched EFA (TX counters were near zero). PP1/EP4 forces expert groups to span both nodes. NIC counters, not exit codes, are the gate.
| vLLM all2all backend | DeepEP V1 call | regime | EFA status |
|---|---|---|---|
| deepep_high_throughput | Buffer.dispatch / combine | prefill & decode | works on 3.6.5 & 3.7.0 — BEST TPOT on EFA, use this |
| deepep_low_latency | Buffer.low_latency_dispatch / combine | decode | 3.7.0 only; 29–75% worse TPOT than HT on EFA under vLLM (SGLang inverts this — see Capstone-2) |
Verified in vLLM distributed/device_communicators/all2all.py:
DeepEPHTAll2AllManager → deep_ep.Buffer(...); DeepEPLLAll2AllManager →
Buffer.get_low_latency_rdma_size_hint + low_latency_dispatch.
deepep_high_throughput / deepep_low_latency.deepep_aws_efa.patch
(DeepEP 567632d). Capstone serving = vLLM v0.11.0 EP16 (enforce-eager) + Capstone-2 SGLang 0.5.5.post3 EP16 (2026-07-07),
both Qwen3-30B-A3B-FP8. Capstone-3 Megatron training (2026-07-08): stock Megatron-LM @23dd639c trains over V1 with zero
patches, numerics match V2 digit-for-digit. Capstone-4 NeMo-RL GRPO (2026-07-08): stock NeMo-RL @46be4e8 drives full
GRPO loop (rollout→reward→train→refit) through V1, 3/3 steps PASS, 537 GB/node EFA TX.
Gap-closure retest (2026-07-08): vLLM eager-confound resolved via CUDA graphs (level-0/FULL); LL beats HT in
decode (-13/-14%), dense A/B complete (LL 1.06-1.08× dense decode, HT 0.89-0.93× dense). Evidence: commit 55c322a,
capstone/results/{cudagraph-retest,dense-ab}/.
Reproducible repo + raw logs + the 3-file serving recipe (Dockerfile / serve.yaml / run_test.sh):
github.com/dmvevents/deepep-efa-ab-h200 (see capstone/).
Campaign rollup + V1-vs-V2 comparison gist (private): available on request; all numbers trace to capstone/ in the evidence repo.
Sanitized — no internal IPs, registry IDs, or hostnames.