feat(deepep-efa): vLLM DeepEP-V2 MoE all-to-all over EFA (eager + non-eager) - #1230
feat(deepep-efa): vLLM DeepEP-V2 MoE all-to-all over EFA (eager + non-eager)#1230dmvevents wants to merge 25 commits into
Conversation
README + benchmarks (verified eager 4.8->301.8 / non-eager 5.0->239.7 tok/s + provenance table + honest caveats), recipe/ (build_deepep, serve, noneager-fix-stack, benchmark_probe), kubernetes/ 2-node yaml, .gitignore (raw/ matches write path). Mirrors ../../sglang/dsr1-deepep-efa layout, built to KeitaW's awslabs#1215 review rubric. TODO (Workflow A finish): setup_deepep_v2_efa.sh (distinct name — dodges the 567632d vendor-sync gate), primary Dockerfile (vendored-script), recipe wrappers benchmark.sh/verify-image.sh, setup/build-push.sh+env_vars.example, MIT-0 headers all files, rubric-scrub copied scripts (no HF_TOKEN under set -x, no ||true-swallow, no hardcoded NIC).
…-eager)
Complete test-case (finishes the WIP scaffold): Dockerfile (NGC-from-scratch, house-pattern
COPY setup_deepep_v2_efa.sh + ldconfig single-NCCL fail-loud guard), setup_deepep_v2_efa.sh
(distinctly named to stay outside the setup_deepep_efa.sh/567632d vendor-sync gate; aws-ofi GIN
9c44d34 + PR#1354 param + DeepEP b306af06 + PR#612 immutable-SHA), recipe/{build_deepep,serve
(eager+non-eager, EP_REUSE_NCCL_COMM=0 segfault fix),apply-noneager-fix-stack,benchmark,
verify-image (fail-loud),benchmark_probe}, setup/{build-push,env_vars.example (user ECR)},
kubernetes/2-node yaml (placeholder image), README + benchmarks/README (measured eager 4.8->301.8 /
non-eager 5.0->239.7 tok/s + provenance table + caveats). Built to KeitaW's awslabs#1215 review rubric;
MIT-0 headers all files; docker build --check clean; all versions ARG-pinned, no 'latest'.
…e (KeitaW-rubric pass) - benchmark_probe.py: add --url/--out argparse + write JSONL (benchmark.sh grep'd a never-written file → exited 1 on every good run) - kubernetes YAML: /opt/serve_vllm.sh → /opt/serve.sh (CrashLoop), drop dead ../docker + GUIDE-PROVENANCE + docs refs - add recipe/run-kernel-test.sh: pre-model cross-node EFA smoke (DeepEP test_ep.py + efa-direct banner assert), wired into Dockerfile + README - README/serve.sh: fix serve_vllm.sh self-name, StatefulSet (not LWS) wording, drop unshipped-Slurm claim, note vendor-sync exemption - vllm index row: EKS-only (was over-claiming Slurm)
…r path only Per the repo's no-patches rule: remove recipe/apply-noneager-fix-stack.sh (cherry-pick + build-time source rewrite of vLLM). Eager (--enforce-eager) is the shipped + supported path. Default compilation is documented as pending the empty-ExpertTokensMetadata guard now filed upstream (vLLM PR <PENDING-PR>); once merged, a pin bump enables it with no recipe change. Historical non-eager measurements in benchmarks/ relabeled as taken with the then-unmerged guard. Signed-off-by: Anton Alexander <dmvevents@gmail.com>
Signed-off-by: Anton Alexander <dmvevents@gmail.com>
|
Re-scoped per the repo's no-patches rule — thank you for stating it plainly rather than letting it surface in review. What changed (this push):
This keeps the case alive across pin bumps by construction: nothing in the build rewrites upstream source. |
…put format ldconfig -p prints 'libnccl.so.2 (libc6,x86-64) => /path' — the literal 'libnccl.so.2 => $NCCL_ROOT/lib' pattern cannot match, so the build failed 100% at this step. Assert the first resolver line instead, and verify it points at the pinned pip NCCL (2.28.x lacks the GIN/LSA symbols aws-ofi-nccl's GIN plugin needs). Caught by building the case exactly as the README instructs, post re-scope. Signed-off-by: Anton Alexander <dmvevents@gmail.com>
…table head), not #1354 aws-ofi-nccl#1354 was scoped down on 2026-08-14 to carry only the v1-pin fallback (already baked in the pinned base 9c44d34) so it no longer overlaps #1351 — which now owns the OFI_NCCL_GDRCOPY_FORCED_PCIE_COPY param this case needs. Cherry-picking today's #1354 head therefore conflicts with the base, and the script's own fail-loud param assert would reject it anyway. Pin #1351 at its immutable head c2e773df (verified: applies clean on 9c44d34, param lands) and bake the SHA as the Dockerfile default so a plain 'docker build .' is reproducible — the build flow no longer asks the user to fetch a moving PR head. Caught by building the case exactly as the README instructs. Signed-off-by: Anton Alexander <dmvevents@gmail.com>
…LM wheel layer The vLLM wheel's resolver silently drags nvidia-nccl-cu13 back to torch's 2.28.9 (and nvshmem to 3.4.5) — into the same directory, so the Layer-3 precedence assert stays green while the GIN/LSA device symbols vanish and DeepEP's nccl.cu fails to compile in-pod (ncclGetLsaDevicePointer / ncclCommQueryProperties undefined, reproduced 2-node H200). The sibling GDAKI case already re-pins LAST (its Layer 8); mirror it here with a fail-loud GIN-symbol assert on both the headers and the .so. Caught by deploying the case exactly as the README instructs. Signed-off-by: Anton Alexander <dmvevents@gmail.com>
…quires it compiled in Without gdrapi.h at configure time the plugin builds with 'GDRCopy support not available', nccl_ofi_gin_init fails at serve, and DeepEP's ElasticBuffer asserts ginType==NCCL_GIN_TYPE_NONE (reproduced 2-node H200, all 16 ranks). Add the gdrcopy v2.5.2 layer (same as the sibling GDAKI case) and a fail-loud setup assert that the compile-gated runtime-warn string is ABSENT from the built plugin — so a gdrapi-less build can never ship silently again. Caught by deploying the case exactly as the README instructs. Signed-off-by: Anton Alexander <dmvevents@gmail.com>
|
Follow-up: the re-scoped eager path is now live-tested end-to-end from this branch — image built exactly per the README ( The live gate caught four defects in the case as previously pushed, all fixed in the four commits above:
Still zero patches: every fix is Dockerfile/pin hygiene; nothing rewrites upstream source. |
KeitaW
left a comment
There was a problem hiding this comment.
Review Batch 1/6: Pre-flight Gates & Verification Scripts
The two scripts the README tells a reader to run before committing a node to a multi-hundred-GB weight load cannot report success as written. This is the batch that most determines the verdict: everything else in the sample is in good shape, and these gates are the sample's own safety story.
KeitaW
left a comment
There was a problem hiding this comment.
Review Batch 2/6: Benchmark Methodology & Measurement Integrity
The tables are honest about what was run and the caveats section is better than most. These findings are about what the numbers can support, not about whether they were taken in good faith.
No warmup, so the conc=1 row absorbs one-time initialization
The first level runs against a server that has not yet served a request, so it carries first-request initialization that later levels don't. Since conc=1 is also the row the PR body quotes as the low endpoint, an unmeasured warmup request before the sweep would make the levels comparable to each other and across the two execution modes.
The comparison a reader most wants is the one measurement not present
serve.sh hardcodes --all2all-backend deepep_v2, and every table measures that one backend, so the sample can't answer the question a reader arrives with: is DeepEP-V2 over EFA faster than what vLLM already does by default on this hardware? Because a test case in this repo functions as a recommendation, the absence reads as an implied yes.
Worth sharing as a data point rather than a correction, since our hardware differs: on 2× p6-b200 with DeepSeek-V2-Lite-Chat at DP16/EP16, the same vLLM pin (e2f993dc4), both arms --enforce-eager, EP_EFA_MAX_QPS=2, n=3, we measured deepep_v2 against allgather_reducescatter and the stock backend was not the strawman one might expect. On short-prefill agent traffic it was near parity on throughput (deepep_v2 345.9 vs allgather 336.9 tok/s, +2.7% for deepep_v2) with allgather 25-30% lower p50. On long-prefill RAG-shape traffic allgather won outright: 449.25 vs 329.80 tok/s (+36.2%) and p50 4.50 s vs 6.18 s. Zero request failures in every run of every arm.
Different GPU generation, different model (64-expert with shared experts vs your 128-expert Qwen3), different traffic shape, and both arms paying the eager tax, so this predicts nothing about your p5en/Qwen3 configuration. But it is enough to say that adding one allgather_reducescatter sweep on the same pods would turn this from "how to enable DeepEP-V2 on EFA" into "and here is when it helps", which is the more useful sample. Failing that, a caveat noting no alternative-backend baseline was measured would keep a reader from over-reading the tables.
KeitaW
left a comment
There was a problem hiding this comment.
Review Batch 3/6: Reproducibility & Cross-File Consistency
KeitaW
left a comment
There was a problem hiding this comment.
Review Batch 4/6: Container Build & Pin Hygiene
The pin discipline here is genuinely strong, see batch 6. These are the rough edges around it.
Truncating the build log hides the diagnostic a failed build needs
python3 setup.py build_ext --inplace 2>&1 | tail -30 keeps only the last 30 lines, which for an nvcc failure is usually the generic "error: command failed with exit status 1" tail rather than the actual compiler diagnostic. Writing the full output to a file and tailing that would keep the console tidy without losing the evidence.
KeitaW
left a comment
There was a problem hiding this comment.
Review Batch 5/6: Kubernetes Manifest & Runtime Posture
The headless Service advertises port 8000 on workers that run no API server
The Service selects app: vllm-deepep-v2, which matches both replicas, and publishes port 8000. But workers launch serve.sh worker … --headless, which starts no HTTP server, so resolving the Service name for HTTP round-robins into connection-refused roughly half the time. Keeping the headless Service for dp-rpc and adding a second Service selecting statefulset.kubernetes.io/pod-name: vllm-deepep-v2-0 for HTTP would make the endpoint predictable.
hugepages-2Mi: 5120Mi is an unusual requirement to carry without a note
This is the only manifest in 3.test_cases/ that requests hugepages, and hugepages-2Mi is only allocatable if the node pre-allocated 2 MiB hugepages at boot, otherwise the pod sits Pending with no obvious explanation. I want to be careful not to overstate this: on the p6-b300 nodes I tested, hugepages were pre-allocated (42,242 Mi allocatable) and the pod scheduled without trouble (verified live, 2026-08-18). So this is not universally broken, and if EFA/libfabric needs it in your configuration that is worth stating. A one-line comment on what pre-allocates them would save the next reader a confusing Pending.
Two smaller manifest notes
privileged: true already grants all capabilities, so the explicit capabilities.add: [IPC_LOCK] is redundant (harmless, but it reads as though it were doing work). And the work emptyDir's sizeLimit: 900Gi draws on node ephemeral storage, on an AMI whose /var/lib/kubelet sits on the root EBS volume that is either unsatisfiable or an eviction mid-run; a pointer to the instance-store mount would make the intent explicit.
KeitaW
left a comment
There was a problem hiding this comment.
Review Batch 6/6: Tuning, Positives & Sources
Things That Look Great
I built this image from the branch and ran what I could of it, so these are checked rather than skimmed.
The pin discipline is the best I've seen in a test case here. Every pin is justified inline, both PR references use immutable head SHAs with the moving-ref trap called out explicitly in the comments, and the git merge of DeepEP #612 at 28d1f7fb reproduces exactly (the staged tree's git log shows the three #612 commits). I checked the whole reference chain and it holds: DeepEP #727 and vLLM #52632 are both open and authored by you, aws-ofi-nccl #1351 is at c2e773df and is a single commit, so the git cherry-pick you use for it is correct, not a partial application, the FALLBACK_V1_FOR_GDRDRV_24 marker really is present at 9c44d34, and the pinned vLLM wheel URL returns HTTP 200 (verified live, 2026-08-18).
The Layer 5b re-pin is the kind of thing that saves the next person a day. I watched it happen during my build: the vLLM wheel layer pulled nvidia-nccl-cu13 back down to 2.28.9 and nvshmem to 3.4.5, and Layer 5b restored 2.30.4/3.6.5 with the symbol assert passing. Documenting it as "any pip layer added later must keep this re-pin LAST" rather than just fixing it silently is what makes it durable, we hit this same transitive downgrade independently and would have saved the debugging had this comment existed.
The fail-loud build asserts are placed at the right seams, and one of them is load-bearing in a way that's easy to miss: the check that GDRCopy support not available at compile time does not appear in the built plugin. I confirmed it comes out clean (0 occurrences), along with ncclGinPlugin and the GIN/LSA symbols. That assert is exactly what stops the failure your last commit fixed from shipping silently again.
Both integration fixes went upstream instead of into local patch files, and the re-scope to a zero-patch sample is the right call for a repo where pins move, a .patch applied at build time rots silently when upstream shifts, whereas a pin bump either works or fails loudly. Documenting the non-eager path as pending an upstream merge, with a refusal gate in serve.sh behind an explicit acknowledgement variable, is a more honest shape than shipping it half-working.
The EP-divisibility preflight is a real gate, not decoration. I ran it three ways against the live Hub: Qwen/Qwen3-30B-A3B-FP8 at DP16 passes with 128 routed experts, Qwen/Qwen1.5-MoE-A2.7B is correctly refused at 60 experts (reproducing the worked example in your own comment), and a dense Qwen3-8B is correctly refused with the not-a-routed-MoE message. Both failure modes fire, which is more than most preflights manage. It also confirms the README's claim that the default model is public and needs no token.
The measurement reporting is more honest than the norm here, HTTP-200 counts alongside throughput rather than throughput alone, the c=64 non-eager regression reported against interest and explicitly marked as not root-caused, and a caveats section that names pod age, the single sweep, and the absence of variance bars. The batch-2 findings are about what the numbers can support; none of them are about good faith.
The manifest documents its own portability seams, per-instance EFA NIC counts, the EP32 scale seam, and a measured justification for privileged: true with the unprivileged alternative named. That last one is exactly the "one-line rationale for a deliberate security-relevant choice" pattern this repo asks for.
Placement and layout are right. It mirrors the merged sglang/dsr1-deepep-efa exemplar, the index table row is added, MIT-0 headers are on all 15 new files including .gitignore (I checked all of them, not a sample), and the reasoning for keeping setup_deepep_v2_efa.sh out of the NVSHMEM vendor-sync workflow is sound and stated where the next person will find it.
One thing outside this PR's scope, offered only as an FYI since your "H200 only, no Blackwell serving run" limitation is well placed: I tried this on 2× p6-b300 and DeepEP's runtime JIT can't produce a loadable kernel there at this pin. get_arch maps every major-10 device to sm_100f and ptxas rejects the generated PTX (Arguments mismatch for instruction 'mov'); forcing sm_100a assembles but won't load (CUDA_ERROR_NO_BINARY_FOR_GPU, since a targets are arch-specific), and forcing native sm_103a hits the same ptxas error. I checked before attributing it: get_arch is unchanged on DeepEP main, nothing since b306af06 touches it, and no DeepEP issue mentions that ptxas error. Scoping it honestly, issues #590/#608/#622 show people getting real numbers on B300 via the Hybrid-EP paths, so this is "closed on sm_103 with CUDA 13.0 at this pin", not "B300 is unsupported". Nothing here touches your p5en results.
Sources
Upstream code and PRs
- DeepEP
tests/elastic/test_ep.pyanddeep_ep/utils/envs.pyat the pinnedb306af06, https://github.com/deepseek-ai/DeepEP/blob/b306af06afd412c88e51e71802951606e40b7358/tests/elastic/test_ep.py - vLLM #52632 (empty-
ExpertTokensMetadataguard), vllm-project/vllm#52632 - vLLM #47785 (
expert_id < 0guard inmoe_align_sum_kernels.cu, merged 2026-07-10), vllm-project/vllm#47785 - vLLM #46432 / #46404, vllm-project/vllm#46432 · vllm-project/vllm#46404
- DeepEP #612 (EFA auto-QP cap) and #727, deepseek-ai/DeepEP#612 · deepseek-ai/DeepEP#727
- aws-ofi-nccl #1351 and the
6e504dbseq-window redesign, aws/aws-ofi-nccl#1351
Verified live, 2026-08-18
grep -ciE "passed|\bPASS\b|all tests? ok"ontest_ep.py@b306af06→0(no pass marker exists forrun-kernel-test.sh:41to match)docker buildof this branch's Dockerfile → succeeds;python3 -c "import deep_ep"in the resulting image →ModuleNotFoundError,/opt/DeepEPabsent fromsys.pathpip3 --versionin the built image →pip 22.0.2;pip3 install --help→ 0 occurrences ofbreak-system-packages- EFA installer 1.49.0 on
nvcr.io/nvidia/cuda:13.0.0-devel-ubuntu22.04→ installslibfabric1-aws 2.4.0amzn5.0,ibverbs-providers 63.0-1, andlibnccl-ofi-ngc-v3 1.20.0-1(the NGC branch fires; the build still succeeds) gh api repos/aws/aws-ofi-nccl/compare/6e504db...9c44d34→ahead_by: 76gh api repos/aws/aws-ofi-nccl/pulls/1351/commits→ length 1 (single-commit PR; the cherry-pick is complete)- Pinned vLLM wheel URL → HTTP 200, 274,075,589 bytes
cuobjdump --list-elfon the wheel's_C.abi3.so→ SASS sm_75/80/86/89/90/90a/100/120; PTX sm_75/80/90 only- EP-divisibility preflight against the live Hub → Qwen3-30B-A3B-FP8 (128 experts) passes at DP16; Qwen1.5-MoE-A2.7B (60) and dense Qwen3-8B both correctly refused
- 2× p6-b300 run of this branch: manifest schedules,
fi_inforeportsefa-direct,NET/OFI Selected provider is efa, fabric is efa-direct (found 16 nics),build_deepep.shproduces ansm_103_C.sowithElasticBuffer: OK;run-kernel-test.shfails atinit_process_groupand passes that point with--nproc-per-node=1
KeitaW
left a comment
There was a problem hiding this comment.
Thank you! Few comments.
- run-kernel-test.sh: one torchrun proc per node (test_ep.py spawns its own local ranks; DeepEP init_dist reads WORLD_SIZE as a NODE count, so --nproc-per-node=8 double-fanned-out to 128 ranks on 16 GPUs and collided MASTER_PORT 29501 with torchrun's own rendezvous -> NCCL 'invalid usage'). Pass --num-processes $GPUS_PER_NODE explicitly. - run-kernel-test.sh: gate on exit code only — the pinned test is assertion-based and prints no pass marker, so the old grep failed every genuinely green run. - run-kernel-test.sh: drop NET/OFI from the transport assert — that banner also prints for tcp;ofi_rxm fallback, the exact case the check exists to rule out. Only efa-direct / 'Selected Provider is efa' count. - verify-image.sh: stop asserting 'import deep_ep' on the bare image — the _C.so is built in-pod by design, so step 1 of the README exited non-zero on every correctly built image. Assert the staged source (ElasticBuffer + test_ep.py) instead; map /dev/infiniband when present so fi_info can see the EFA device under docker run, with a provider-compiled-in fallback otherwise. - verify-image.sh: the libnccl check now asserts the GIN/LSA symbol (ncclGetLsaDevicePointer), not just the path — the vLLM wheel's 2.28.9 downgrade lands in the SAME directory, so the path check stayed green in precisely the failure mode it existed to catch. Signed-off-by: Anton Alexander <dmvevents@gmail.com>
… pinned denominators benchmark_probe.py: - successes only in latency percentiles + token totals (a partially-dead serve reported BETTER p50 because refused connections return fast) - exit 0 only if EVERY request at EVERY level succeeded (was: any single 200 in the whole sweep passed, under a comment claiming fail-on-any-failure) - requests per level = 5x concurrency so p50/p90/p99 describe distributions (was: one shot per level — at conc=1 the percentiles were one observation) - ignore_eos:true pins generated tokens == max_tokens (fixed tok/s denominator by construction, not by prompt/model luck) - unique prompt prefix per request (index first) so the prefix cache cannot serve prefill for requests 2..N - a 200 with no usage block is a failure (200-no-usage), not a 0-token success benchmark.sh: the probe's exit code is the single pass/fail authority (the old grep -q '"200"' repeated the any-single-200 gate). benchmarks/README.md: relabel the tables as what they are — one concurrency sweep per mode, per-stream latency floor rather than a throughput ceiling (server never saturates: wall flat ~27s while aggregate = concurrency x ~4.75 tok/s); reconcile the 153-vs-121 request count (153 = 31-request warm ramp + 1 coherence check + the 121-request sweep; table rows are the sweep only, same methodology both modes); document the old probe's caveats and that the upgraded probe will not reproduce the tables byte-identically; add the QP knobs (EP_EFA_MAX_QPS=2, EP_EFA_RDMA_GBS=25.0) to provenance. Signed-off-by: Anton Alexander <dmvevents@gmail.com>
… fail-loud pod startup
- ONE image name everywhere: ${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG} from
setup/env_vars (README verify command sourced env_vars in the reader's
shell; manifest example matches; Dockerfile header points at build-push.sh).
Immutable IMAGE_TAG default (v1-20260818) — :latest + IfNotPresent silently
re-ran stale cached images after a rebuild-and-push.
- Dockerfile: derive the vLLM wheel filename from the per-commit index so
bumping VLLM_SHA alone works (filename hardcoded the SHA a second time, so
the README's own 'bump the pin' advice 404'd); fail-loud message names the
garbage-collected-nightly cause. Verified the derived URL resolves HTTP 200.
- Dockerfile: --disable-ngc on the EFA installer — the NGC base ships
/opt/nvidia/nvidia_entrypoint.sh which trips the installer's NGC
auto-detect (installs libnccl-ofi-ngc instead of the normal path); we build
aws-ofi-nccl from source, same explicit choice as the sibling samples.
- Dockerfile: bake ninja at build time + COPY benchmark.sh into /opt (first
boot no longer assumes PyPI egress for the device-link build; the
documented benchmark entry point now exists in the container).
- build_deepep.sh: drop --break-system-packages from all three pip calls —
the image ships pip 22.0.2 and the flag arrived in pip 23.0, so every use
failed; the cu13-toolchain one was ||-true-masked into a wrong-ABI
fallback risk. Corrected the editable-install comment that blamed the
sandboxed rebuild.
- manifest: set -euo pipefail (a failed in-pod DeepEP build reached vllm
serve and died later, obscuring the cause) + empty-LEADER_IP guard;
startup/readiness probes paired with publishNotReadyAddresses:true on the
headless Service (a probe alone would unpublish the leader's A-record and
deadlock the rendezvous workers wait on); worker start-rank uses
SERVE_DP_LOCAL (was a literal 8 contradicting the documented knob);
requests==limits for Guaranteed QoS (CPU-proxy GIN puts proxy-thread CPU
on the data path — CFS throttling under Burstable QoS taints published
numbers); DEEPEP_ARCH_LIST reachable in env: (commented) + p6-b300 row.
- serve.sh: set -e so the three preflights actually stop the launch; reject
unrecognized ROLE; EP_EFA_MAX_QPS provenance note (measured-with value;
+29% tput / -23% p50 uncapped on 2x B200 through this path; the 128-slot
ring the cap guarded against was replaced upstream by the seq-window
design included in the pinned plugin).
- README: scope validation claim to what benchmarks/ shows (measured
DP16/EP16; DP32/EP32 functionally validated); remove the unfilled
<gist-raw> fast-path block (in-tree Dockerfile is canonical and produced
the published numbers); benchmark section shows kubectl exec /
port-forward paths that actually reach the probe; shared-experts non-eager
caveat (vLLM #47785) for the DeepSeek models serve.sh invites.
Signed-off-by: Anton Alexander <dmvevents@gmail.com>
|
All 28 threads from the 08-18 round are answered inline and the fixes are on the branch at
Two things I checked rather than assumed, both from your findings:
Still open and yours to call: |
KeitaW
left a comment
There was a problem hiding this comment.
Review Batch 1/4 — Response-Round Scoreboard & Two Defects Introduced by the Fixes
This is an exemplary response round: three commits (5d133f7, eb72b3f, 0e5f902) resolving all 28 inline findings from round 1, each reply citing its commit. I verified every one against the code rather than the replies, and they all hold — the kernel-test launcher, the exit-code gates, the probe methodology (successes-only percentiles, ignore_eos, unique prompt prefixes, 5× requests per level), the single image name across all five surfaces, the derived wheel URL, --disable-ngc, the baked ninja, Guaranteed QoS, and the honest relabeling of the benchmark tables all check out. The 153-request reconciliation is arithmetically consistent (121 + 31 warm-up + 1 coherence check).
Of the round-1 body findings, the warmup point is partially covered by the 5× multiplier, and the docs now route all HTTP through the leader pod by name (which defuses the Service-port-8000 round-robin in every documented path — a one-line comment on the Service would close the residual trap for anyone who targets the Service name directly). Four smaller body notes are still open; they're carried in batch 4.
Two of the fixes introduced new defects, both in the manifest — the two comments in this batch. Nothing here rises to must-fix, and none of it invalidates the response round.
KeitaW
left a comment
There was a problem hiding this comment.
Review Batch 2/4 — Verification Gates & Benchmark Plumbing
The gates are much stronger than round 1's — these are the remaining seams, all small.
KeitaW
left a comment
There was a problem hiding this comment.
Review Batch 3/4 — Pinning & Config Surface
The pin discipline remains the sample's strongest suit (see batch 4). These close the last gaps between the doctrine and the mechanics.
KeitaW
left a comment
There was a problem hiding this comment.
Review Batch 4/4 — Carried-Forward from Round 1, Positives & Sources
Four round-1 body-level notes are still open. Each is a small, bounded edit; none blocks.
Remaining small notes, grouped
Three leftovers from round 1's smaller notes, none load-bearing: capabilities.add: [IPC_LOCK] is still redundant under privileged: true (harmless; if it's kept deliberately to support the drop-privileged path the header describes, a three-word comment would say so); the work emptyDir's sizeLimit: 900Gi still draws on node ephemeral storage with no pointer to where that lands on the target AMI; and the probe still has no explicit unmeasured warmup request — the 5× multiplier dilutes first-request initialization at conc=1 to one observation in five, which is much better than round 1, so consider this one mostly settled and purely optional.
Things That Look Great
I re-verified the response round item-by-item against the code, not the replies — these are checked.
The response round itself is the model for this repo. Three focused commits, 28 of 28 inline findings resolved, every reply citing its commit, and several fixes going beyond the ask: the exit gate landed as ok == n at every level (stronger than the suggested ok == conc), the wheel-URL fix derives the filename from the per-commit index rather than just documenting the coupling (I re-derived it live: the index href resolves to the exact pinned wheel, HTTP 200, 274 MB — verified 2026-08-19), and the 153-request discrepancy was reconciled with a full arithmetic breakdown rather than a hand-wave — one that checks out (121 + 31 + 1, and every table row's tok/s × wall ≈ n × 128).
The benchmarks README now says exactly what the numbers are. The old probe's three methodology limits are disclosed as caveats on the published tables instead of silently retrofitted, the "per-stream latency floor, not a throughput ceiling" framing is front and center, and the new probe enforces what the old one assumed (ignore_eos, unique prefixes, successes-only accounting, 200-no-usage as a counted failure). The percentile function is a correct linear interpolation. This is now the most honest benchmarks doc in the vLLM tree.
The probe and gate rewrites are real fixes, not appeasements. The kernel test now launches one torchrun per node with the fan-out delegated to the test's own spawner, gates on the exit code, and accepts only provider-specific EFA banners; verify-image.sh asserts what the image actually stages and discriminates the NCCL downgrade by symbol rather than path. The reasoning is written into the scripts as comments, so the next editor knows why each gate has the shape it has.
The leader probe + publishNotReadyAddresses pairing is exactly right — the rendezvous-vs-readiness interaction round 1 worried about is handled, with the reasoning documented in the manifest. (The worker half needs the batch-1 fix, but the structure is correct.)
The pin discipline held through the response round. --disable-ngc matches the sibling samples and is a real flag doing what the comment says (verified in the 1.49.0 installer source: auto-detect defaults on, --disable-ngc is the supported off switch — 2026-08-19); ninja is baked with the air-gap rationale written down; the immutable tag default (v1-20260818) documents the :latest+IfNotPresent trap it replaces; and the new deep_ep/buffers/elastic.py assertion in verify-image.sh targets a path that really exists at the pinned DeepEP SHA (verified live, 2026-08-19).
Sources
Upstream code and PRs
- aws-ofi-nccl PR #1351 (pinned
c2e773d; head now63698ea), aws/aws-ofi-nccl#1351 - DeepEP PR #612 (pinned = current head
28d1f7fb), deepseek-ai/DeepEP#612 - DeepEP
deep_ep/buffers/elastic.pyat the pinnedb306af06, https://github.com/deepseek-ai/DeepEP/tree/b306af06afd412c88e51e71802951606e40b7358/deep_ep/buffers - EFA installer 1.49.0 (
efa_installer.sh:DISABLE_NGCdefault 0,--disable-ngcdocumented off switch), https://efa-installer.amazonaws.com/aws-efa-installer-1.49.0.tar.gz
Verified live, 2026-08-19
pgrep -af 'vllm serve'invoked viabash -c→ matches its own parent shell (/bin/bash -c pgrep -af 'vllm serve' …) on a host with no vLLM process; the bracketedpgrep -f '[v]llm serve'form → no match from the same wrapperbash -c 'set -euo pipefail; LEADER_IP=$(getent hosts nonexistent.invalid | awk … | head -1); test -n …'→ exits 2, FATAL line never prints; with|| trueinside the substitution → FATAL prints, exits 1seq 1 200000 | grep -q 5underset -o pipefail→ exit 141 (SIGPIPE)gh api repos/aws/aws-ofi-nccl/pulls/1351→ head63698ea≠ pinnedc2e773d;git fetch origin c2e773df…(direct SHA fetch) succeeds against GitHubgh api repos/deepseek-ai/DeepEP/pulls/612→ head28d1f7fb= the pin (still additive)gh api repos/NVIDIA/gdrcopy/commits/v2.5.2→c91ad9f178e5(the tag's current commit)- Wheel index for
e2f993dc4→ href../../e2f993dc4…/vllm-0.22.1rc1.dev283%2Bge2f993dc4-cp38-abi3-manylinux_2_28_x86_64.whl, resolves HTTP 200, 274,075,589 bytes benchmarks/README.mdarithmetic recomputed: 121 = 1+8+16+32+64; 153 = 121+31+1; per-row tok/s × wall ≈ n × 128; all five delta percentages recompute correctly
…ion unblocked) vLLM #52632 (empty-ExpertTokensMetadata guard, the last piece for default CUDA-graph compilation) merged 2026-08-20. Bump VLLM_SHA from e2f993dc (PR#41183's first deepep_v2 backend commit) to 14617c2b, #52632's merge commit on main — which also carries #47785 (shared-experts -1 sentinel fix). Wheel for the new SHA verified indexed on wheels.vllm.ai 2026-08-25. README: flip the three 'once #52632 merges' notes to past tense; default compilation now works with the shipped pin and no --enforce-eager, no build-time patch step. This is the 'update branch reference / bump the pin past #52632' action recommended in the sample's own README and in adai#1230. Signed-off-by: Anton Alexander <dmvevents@gmail.com>
…rect-SHA fetches, benchmark provenance - kubernetes/vllm-deepep-v2-2node.yaml:145,150 — worker probe bracket form `[v]llm serve` so the exec-shell's own cmdline no longer self-matches pgrep (thread awslabs#1/awslabs#9) - kubernetes/vllm-deepep-v2-2node.yaml:97 — append `|| true` to the LEADER_IP substitution so the FATAL DNS guard can fire under set -e + pipefail (thread awslabs#2) - kubernetes/vllm-deepep-v2-2node.yaml:159 — hugepages-2Mi comment: needs pre-allocated 2Mi hugepages or the pod sits Pending (thread awslabs#11) - kubernetes/vllm-deepep-v2-2node.yaml:115 — DEEPEP_ARCH_LIST commented env now names 10.0 (b200) + 10.3 (b300) so the Blackwell knob is reachable from the manifest (thread awslabs#12) - recipe/verify-image.sh:24,33,34 — convert fi_info efa-direct, ncclGetLsaDevicePointer, ncclGinPlugin checks from `grep -q` to draining `[ "$(... | grep -c X)" -ge 1 ]` (SIGPIPE-141 flake under pipefail), matching Dockerfile Layer 5b (thread awslabs#3) - recipe/run-kernel-test.sh:16 — worker requires an explicit node-rank (`${3:?...}`) instead of defaulting to 0 and colliding with the leader; add the `case "$ROLE"` guard matching serve.sh (thread awslabs#4) - recipe/benchmark_probe.py:18,24 — MODEL reads SERVE_MODEL env with the current value as fallback (+ `import os`) so a non-default model doesn't 100%-fail (thread awslabs#5) - setup_deepep_v2_efa.sh:30,52 — fetch the immutable PR-head SHA directly instead of the moving `refs/pull/N/head` ref for both aws-ofi-nccl #1351 and DeepEP awslabs#612 (thread awslabs#6) - Dockerfile:116 — CMD banner names /opt/serve.sh + /opt/build_deepep.sh (the in-image paths), not recipe/ (thread awslabs#7) - recipe/build_deepep.sh:120 — `tee /tmp/deepep-build.log | tail -30` so a failed build keeps the full nvcc diagnostic (thread awslabs#8) - Dockerfile:60 — gdrcopy pinned by commit SHA (v2.5.2 == c91ad9f) via fetch/checkout instead of the movable `--branch v2.5.2` tag (thread awslabs#13) - recipe/serve.sh:124 — comment on why --trust-remote-code is unconditional (DeepSeek/Kimi models the preflight supports); chmod 755 serve.sh + run-kernel-test.sh in-tree to match the other four scripts (thread awslabs#14) - README.md:114 — in-pod benchmark exec sets OUT_ROOT=/work/benchmarks so results land on the /work volume, not the ephemeral container layer (thread awslabs#16) - setup/env_vars.example:2,12 — header says build-push.sh sources it and recipe/*.sh need `source` first; reword the AWS_OFI_NCCL_PR_SHA note (empty does NOT skip the cherry-pick) (thread awslabs#17) - benchmarks/README.md:88 — caveat: no alternative-backend baseline measured; every table is --all2all-backend deepep_v2 (thread awslabs#18) - recipe/serve.sh:48 — EP_EFA_MAX_QPS comment records the pinned plugin (9c44d34) is 76 commits past the seq-window redesign (6e504db) so the 128-slot cap's precondition no longer holds; default left unchanged (pods down) (thread awslabs#21) Already present at c025946 (prior commits), verified not duplicated: - README shared-experts caveat naming #47785 + DeepSeek (thread awslabs#15) - benchmark_probe.py requests-per-level distribution + unique prompt prefix (threads awslabs#19/awslabs#20) - probes + publishNotReadyAddresses structure (thread awslabs#9) and requests==limits Guaranteed QoS (thread awslabs#10) Signed-off-by: Anton Alexander <dmvevents@gmail.com>
Round 2 pushed —
|
…e index, de-link unmerged sibling - env_vars.example: default via :- so APPLY_HT_FLAT_PATCH=1 build-push.sh no longer clobbers to 0 - add tensorrt-llm/README.md engine index (Available test cases table, parity with sglang/vllm/nvidia-dynamo) - README.md: de-link the not-yet-merged vLLM DeepEP-V2 sibling (awslabs#1230) to avoid a 404-on-merge - Dockerfile: add org.opencontainers.image.source LABEL (review-optional trivial) Signed-off-by: Anton Alexander <dmvevents@gmail.com>
KeitaW
left a comment
There was a problem hiding this comment.
Review Batch 1/5 — Aligning the environment with the canonical deepep-v2-benchmark
Since round 2, main gained a canonical DeepEP-V2 / NCCL-GIN asset: micro-benchmarks/expert-parallelism/deepep-v2-benchmark (PR #1234, merged 2026-08-24), carrying setup_deepep_gin.sh and a reference deepep.Dockerfile. This sample should be built on that asset rather than beside it — the environment setup needs to align with it.
Its README states the intended consumption pattern in almost exactly this sample's terms: the script installs DeepEP V2 "into your container or environment (for example a vLLM image that already ships a DeepEP)", invoked as ./setup_deepep_gin.sh --nccl-root /path/to/gin-capable/nccl. That is this sample's use case verbatim.
Before the asks, the carve-outs — a wholesale adoption would break this sample, and I want to be precise about which canonical constraints do not transfer. The canonical measures EFA-GDA (NCCL_GIN_TYPE=5, GPU-initiated); this sample deliberately uses the CPU-proxy backend (NCCL_GIN_TYPE=2), and the canonical README says the CPU-proxy path "has no such floor." So these canonical requirements are not binding here: EFA installer ≥ 1.50 / libfabric ≥ 2.5, the host EFA driver ≥ 3.3.0 (efadv_create_comp_cntr), and the ncclGinPlugin_v14 export gate. Nor is the canonical's aws-ofi-nccl pin adoptable: v1.21.1 does not contain the OFI_NCCL_GDRCOPY_FORCED_PCIE_COPY parameter this sample depends on — aws-ofi-nccl #1351 is still open/unmerged (verified live, 2026-08-25), so the cherry-pick must stay. Please keep all four of those as they are.
KeitaW
left a comment
There was a problem hiding this comment.
Review Batch 2/5 — The vLLM pin bump: the docs say unblocked, the code still refuses
c0259466 bumps VLLM_SHA to 14617c2b, which I verified is exactly the merge commit of vLLM #52632 (merged 2026-08-20) — the fix this sample has been waiting on. The claim is sound and the READMEs were updated. But the bump only landed in the docs: the runtime still enforces the old pin's policy, and the sample's headline new capability is blocked by its own gate.
What run demonstrates default compilation at the new pin?
The eager/non-eager table now states default compilation "works without --enforce-eager" at this pin, and the round-2 comment refers to 14617c2b as "the E2E-verified pin", but I couldn't find a posted run at it — the sweeps in benchmarks/ are explicitly historical (old pin, then-unmerged guard). Given the version jump, could you say what was actually exercised: a full serve, or the import/preflight path? Two things I checked that support the bump and narrow what's left to verify — every flag serve.sh passes (--all2all-backend, --data-parallel-start-rank, --data-parallel-size-local, --enable-expert-parallel, --data-parallel-backend) still exists in arg_utils.py at 14617c2b, DeepEPV2All2AllManager is still at the path the preflight imports, and the wheel index resolves (HTTP 200) for that SHA (all verified live, 2026-08-25). So the remaining question is runtime behaviour, not the interface. If a fresh non-eager run isn't practical right now, softening to "expected to work at this pin; not yet re-measured" would carry the same information honestly.
KeitaW
left a comment
There was a problem hiding this comment.
Review Batch 3/5 — Where my round-2 fixes landed but didn't finish the job
Three of the round-2 fixes are correct as far as they go and still leave the original problem standing. I'd rather flag these than let the checkmarks imply more than they do — in each case the fix addressed the mechanism I named while the property I was actually asking for is still unmet.
KeitaW
left a comment
There was a problem hiding this comment.
Review Batch 4/5 — Strict-mode and residual correctness
KeitaW
left a comment
There was a problem hiding this comment.
Review Batch 5/5 — Round-2 verification, Positives & Sources
Things That Look Great
Round 2 was resolved completely, and I checked the code rather than the replies. All 14 findings are fixed at 2abb4e4d — each addressing the mechanism I named, though three of them leave the underlying property still unmet (batch 3): the bracket trick on both probe branches, || true on the DNS assignment so the FATAL guard is reachable, the draining grep -c form on all three image checks, ${3:?} plus a case role-guard in run-kernel-test.sh, os.environ.get("SERVE_MODEL", …) in the probe, OUT_ROOT=/work/benchmarks on the in-pod exec, direct-SHA fetches for both PR pins, gdrcopy pinned to c91ad9f, the /opt-correct CMD banner, the trust-remote-code rationale, chmod 755 on the two scripts, and the three carried-forward doc items. Two of those went beyond the ask — the role-guard was volunteered as a sibling to serve.sh, and serve.sh picked up the same treatment.
The ARG parse trap you caught pre-push is a genuinely good find, and the mechanism is sharper than the note suggests. I reproduced it: a plain trailing comment after ARG parses fine on both builders, but a comment containing == fails with dockerfile parse error: ARG names can not be blank — because ARG accepts multiple space-separated names and == tokenizes to one with an empty name. That's why the sample built for months with four other inline ARG comments and only the gdrcopy one broke. I ran docker build --check against the shipped Dockerfile and it's clean, so the remaining inline comments are safe. Worth keeping the full-line-comment habit anyway, since the trap is invisible until it fires. (An independent pass flagged all inline ARG comments as build-breaking; that's the over-general version of your finding, and the empirical check rules it out.)
The pin-bump reasoning checks out where it can be verified. 14617c2b really is #52632's merge commit (merged 2026-08-20), the wheel index resolves for it, and — the part that's easy to get wrong — the shared-experts claim holds: vLLM #47785 is an ancestor of this pin, so the README's "any pin past #52632 also includes #47785" is correct rather than merely plausible (verified live, 2026-08-25). The serve.sh preflight that imports DeepEPV2All2AllManager is also exactly the right gate to have kept across a four-minor-version jump.
The verification scripts now discriminate. After round 2 the image checks assert the winning libnccl by symbol, the EFA banner by provider-specific pattern, and the staged DeepEP by ElasticBuffer class — and all of them drain their producers. That combination is what makes "ALL CHECKS PASS" mean something, and it's better than the canonical benchmark's own equivalent in one respect: it fails loudly on a partially-correct image rather than on a missing one.
Sources
Canonical asset (the alignment target)
micro-benchmarks/expert-parallelism/deepep-v2-benchmark(PR #1234, merged 2026-08-24), https://github.com/awslabs/awsome-distributed-ai/tree/main/micro-benchmarks/expert-parallelism/deepep-v2-benchmarksetup_deepep_gin.sh— "for example a vLLM image that already ships a DeepEP";--nccl-rootgate oninclude/nccl_device.hdeepep.Dockerfile—ENV NCCL_SOCKET_IFNAME=^docker,lo,veth; CUDA 13.1.2 default; the ptxas 13.0.88 /st.bulknote- Repo IFNAME convention: https://github.com/awslabs/awsome-distributed-ai/blob/main/micro-benchmarks/nccl-tests/nccl-tests.Dockerfile
Upstream
- vLLM #52632 (merge commit
14617c2b, merged 2026-08-20), vllm-project/vllm#52632 - vLLM #47785, vllm-project/vllm#47785
- aws-ofi-nccl #1351 — still open, aws/aws-ofi-nccl#1351
- amazon-contributing/DeepEP #3 (
st.bulk64-bit operand, merged 2026-08-24), amazon-contributing/DeepEP#3
Verified live, 2026-08-25
gh api repos/vllm-project/vllm/commits/14617c2b…→ "[Bugfix] DeepEP-V2: expert_tokens_meta must be None … (#52632)";pulls/52632.merge_commit_sha=14617c2b…compare/14617c2b…{#47785 merge}→ahead_by: 0(⇒ #47785 is an ancestor of the pin)gh api repos/aws/aws-ofi-nccl/pulls/1351→merged: false;nccl_ofi_param.h @ v1.21.1→ 0 occurrences ofGDRCOPY_FORCED_PCIE_COPYnvidia_nccl_cu13-2.30.4wheel → shipsinclude/nccl_device.h+nccl_device/gin/proxy/gin_proxy.h- vLLM
arg_utils.py @ 14617c2b→ all fiveserve.shflags present;all2all.py→class DeepEPV2All2AllManagerpresent - Wheel index for
14617c2b→vllm-0.26.1rc1.dev1000+g14617c2b6-…x86_64.whl, HTTP 200 ARG V=x # plain commentbuilds;ARG V=x # comment with ==→dockerfile parse error: ARG names can not be blank(both BuildKit and legacy, Docker 29.7.2);docker build --checkon the shipped Dockerfile → "Check complete, no warnings found"set -euo pipefail; V="$(ls -d <existing> <no-match-glob> 2>/dev/null | head -1)"→ exits 2, recovery line never reachedNCCL_SOCKET_IFNAME/NCCL_GIN_PLUGIN/nccl_device/amazon-contributing→ 0 occurrences each in the PR diff
…NAME, derived worker rank, pinned model revision serve.sh no longer refuses SERVE_ENFORCE_EAGER=0. The VLLM_SHA pin (14617c2b) IS vLLM #52632's merge commit (verified: gh api pulls/52632 merge_commit_sha == the pin; merged 2026-08-20), so the empty-ExpertTokensMetadata guard that fixed the deterministic profile_run combine crash at the old e2f993dc4 pin is in the shipped wheel. Dropped the exit-4 gate, the SERVE_I_UNDERSTAND_NONEAGER_CRASHES bypass, and the post-bypass crash warning; rewrote the header to describe the pin's real state (eager stays the default because it is what benchmarks/ was measured with; non-eager was not re-measured at this pin). Also in this file, from the same review round: - NCCL_SOCKET_IFNAME=^lo,docker,veth (exclusion form, repo convention) so the DP bootstrap cannot pick a non-routing CNI/bridge iface -> rendezvous hang. - worker START_RANK default derives from SERVE_DP_LOCAL, not a hardcoded 8, so the documented manual worker path is correct on non-8-GPU nodes. - SERVE_MODEL_REVISION threaded into both the preflight hf_hub_download and vllm serve (--revision), defaulting to the measured commit of the default model: --trust-remote-code runs repo code in-pod, so pin which commit runs. Signed-off-by: Anton Alexander <dmvevents@gmail.com>
…est timeout, probe integrity)
build_deepep.sh:
- NVSHMEM fallback `ls -d A B` prints A but exits 2 when only A exists; under
set -euo pipefail + | head that aborted the very fallback it provides. Added
`|| true` to both occurrences (site-packages resolve + verify-step re-resolve).
- cu13 toolchain pip install no longer masked by `|| true`: a masked failure
(no egress, resolver conflict, no disk) was indistinguishable from success and
silently fell back to the base /usr/local/cuda = the wrong-ABI build this block
exists to prevent. Now fails loud; the shipped cu13 base takes the FAST PATH and
never reaches this branch, so this only affects a non-canonical cu12 base.
run-kernel-test.sh: wrapped the torchrun gate in `timeout ${KERNEL_TEST_TIMEOUT:-600}`
so the "one step that cannot hang for hours" is enforced, not just asserted (a
wrong NNODES / absent worker / stalled NCCL init would block indefinitely).
timeout exits 124, which the existing rc check reports as FAIL.
benchmark_probe.py:
- prompt idx now unique ACROSS levels (f"{conc}-{i}"), not just within one:
range(n) restarted at 0 each level so higher-conc levels got a share of cached
prefill, biasing them favourably — the exact effect the round-1 unique-prompt
fix was written to remove.
- record r.status, not a literal 200 (a 2xx that isn't 200 was misreported).
- under ignore_eos:true, assert completion_tokens == max_tokens (fail the request
otherwise) so the fixed denominator is enforced, not assumed.
- reject --requests-per-level-mult < 1 (0 fired no requests and exited 0 with
empty tables, defeating the fail-loud contract).
Signed-off-by: Anton Alexander <dmvevents@gmail.com>
…, honest probe/ordering/service-port comments, exec probe timeouts Reconciles the 2-node StatefulSet manifest with the shipped pin and the recipe scripts, per round-3 review: - SERVE_ENFORCE_EAGER knob comment: 0 = default compilation, unblocked by vLLM #52632 (which this pin carries) — was described as blocked. - image tag v1-20260818 -> v2-20260825 with a keep-in-sync note pointing at setup/env_vars.example (IfNotPresent caches by tag; the tag must postdate the pin bump). - http service-port (:44): note that headless + publishNotReadyAddresses makes the name resolve to workers (no HTTP server) and to a not-ready leader — address vllm-deepep-v2-0 directly for the API. - ordering comment (:103): corrected — order is NOT enforced (podManagementPolicy: Parallel); the DP rendezvous tolerates a worker reaching serve.sh first by retrying. - worker probe comment (:138): corrected to match code — workers are --headless so the probe is process-liveness only; the 60-min compile+load budget applies to the leader, not workers. - startupProbe + readinessProbe: add timeoutSeconds: 5 (exec probes inherit K8s' 1s default; a busy vLLM /health can exceed it -> false readiness flap). Signed-off-by: Anton Alexander <dmvevents@gmail.com>
…2/GIN script Round-3 doc-drift: the VLLM_SHA bump (e2f993dc4 -> 14617c2b, #52632's merge commit) and the appearance of the canonical setup_deepep_gin.sh (2026-08-24) left several docs describing the OLD state. Reconciled WITHOUT fabricating any new measurements — the benchmark tables were measured on the old pin and are now labeled historical, not re-claimed on the new pin. - README setup-script rationale (awslabs#1): reworked to point at the canonical micro-benchmarks/.../deepep-v2-benchmark/setup_deepep_gin.sh and name the three deliberate divergences (unmerged aws-ofi-nccl #1351 param; CPU-proxy vs EFA-GDA; vLLM-wheel torch/NCCL ABI coupling). Kept the correct vendor-sync point (that CI gates only the NVSHMEM setup_deepep_efa.sh). Did NOT adopt the 'delete the DeepEP half + call the canonical' substitution — that needs a docker build to verify and this change set is docs-only. - DeepEP source divergence + Blackwell (awslabs#2): setup_deepep_v2_efa.sh header note + README Known-limitations now state the source is deepseek-ai/DeepEP@b306af06 (not the amazon-contributing fork the canonical pins) and mark the manifest's DEEPEP_ARCH_LIST=10.x knobs documented-but-not-verified — round-1 saw no loadable Blackwell kernel at CUDA 13.0 on this lineage; the fork's st.bulk 64-bit fix (amazon-contributing/DeepEP#3) is the enabling path, to re-verify. - Provenance honesty (awslabs#6/awslabs#9/awslabs#10): benchmarks/README vLLM row + README build note now disclose the shipped image is 0.26.1rc1.dev1000+g14617c2b6 (four minor versions past the measured 0.22.1rc1.dev283+ge2f993dc4); eager table labeled historical to match the non-eager one; 'remain representative' -> 'historical, not what a rebuild produces'; probe-diff note -> 'not directly comparable'. - Saturation framing (awslabs#13): scoped the ~4.75 tok/s per-stream-flat claim to the EAGER sweep; noted the non-eager c=64 wall rise (26.61->34.18s, 3.75 tok/s). - Dockerfile Layer 5 heading (awslabs#7): old-pin identity (PR#41183 first deepep_v2 commit) -> #52632's merge commit, matching the block below it. - env_vars.example tag (awslabs#8): v1-20260818 -> v2-20260825 (postdates the pin bump; IfNotPresent caches by tag). - README serve section (awslabs#4 sub-ask): name SERVE_ENFORCE_EAGER=0 as the knob. Signed-off-by: Anton Alexander <dmvevents@gmail.com>
… build context) .gitignore does not apply to the Docker build context, so build-push.sh's `docker build .` uploaded the gitignored setup/env_vars (your ECR URI) to the daemon/CI builder on every build. The Dockerfile COPYs named files (never COPY . .), so nothing was baked into a layer and the example holds a URI not a token — a small exposure, not a leak — but excluding it from the context closes it. benchmarks/raw/ is measurement output, never a build input. Signed-off-by: Anton Alexander <dmvevents@gmail.com>
…the smoke-test section The README referenced the canonical folder only deep in Known limitations (as the provisioner's canonical source); readers looking for a standalone fabric benchmark (numbers, not pass/fail) had no pointer at the natural spot. Add one line after the kernel-smoke step linking micro-benchmarks/expert-parallelism/deepep-v2-benchmark/ (merged awslabs#1234). Signed-off-by: Anton Alexander <dmvevents@gmail.com>
… 'VERBATIM from serve.sh' true) The kernel-smoke env block is documented as VERBATIM from serve.sh, but the NCCL_SOCKET_IFNAME line added to serve.sh (ad39fbc) was never mirrored here, so the two transport contracts diverged on the one iface-selection knob. Add the identical exclusion-form default so the claim holds and the smoke exercises the same NCCL interface-selection behaviour serve.sh runs under. Addresses KeitaW review on awslabs#1230 (serve.sh:L35 thread — 'neither ... run-kernel-test.sh'). Signed-off-by: Anton Alexander <dmvevents@gmail.com>
… (reorg awslabs#1119) Reorg awslabs#1119 de-numbered the top-level dirs and moved test cases from 3.test_cases/pytorch/<framework>/ to examples/inference/<engine>/. This PR was opened against the pre-reorg path, so its files landed under the now- deleted 3.test_cases/ tree (mergeable=false). Move the sample to its reorg'd home with `git mv` (history preserved) and add the framework-index row in examples/inference/README.md. The per-engine case-index row in examples/inference/vllm/README.md was carried over automatically by the merge's rename detection. Directory depth is unchanged (3.test_cases/pytorch/vllm/deepep-v2-efa and examples/inference/vllm/deepep-v2-efa are both 4 levels), so every relative link in the README resolves at the new location without edit: ../../sglang/dsr1-deepep-efa -> examples/inference/sglang/dsr1-deepep-efa (exists) ../../../../micro-benchmarks/expert-parallelism -> repo root (unchanged) Merged upstream/main rather than rebased to preserve the commit SHAs cited in the resolved review-thread replies. No functional change to the sample. Signed-off-by: Anton Alexander <dmvevents@gmail.com>
…/fences/lists) Conform the sample's README + benchmarks/README to the repo markdownlint ruleset, matching the repo-wide sweep in awslabs#1245. Whitespace-only: blank lines inserted around headings (MD022), fenced code blocks (MD031), and lists (MD032). Verified `git diff --ignore-blank-lines` is empty — zero content change. `markdownlint-cli2 examples/inference/vllm/deepep-v2-efa/**/*.md` reports 0 errors. Signed-off-by: Anton Alexander <dmvevents@gmail.com>
Adds
3.test_cases/pytorch/vllm/deepep-v2-efa/— the V2/NCCL-GIN counterpart to the mergedsglang/dsr1-deepep-efa(#1215). Serves an MoE on vLLM with DeepEP-V2ElasticBufferall-to-all over EFA via the aws-ofi-nccl GIN CPU-proxy (NCCL_GIN_TYPE=2), no NVSHMEM/IBGDA.Both execution modes measured on 2× p5en (H200), Qwen3-30B-A3B-FP8 DP16/EP16: eager 4.8→301.8 tok/s (121/121 HTTP 200), non-eager 5.0→239.7 tok/s (153/153 HTTP 200). Full tables + environment provenance in
benchmarks/README.md.Two integration fixes are baked in + documented: (1)
EP_REUSE_NCCL_COMM=0(stock DeepEP-V2 null-derefsncclTeamWorldunder vLLM's lazy torch comms — deterministic serve-init segfault; the guard is also filed upstream as deepseek-ai/DeepEP#727); (2) the gdrcopy forced-PCIe capability via aws-ofi-nccl#1354. Non-eager needs vLLM #46404+#46432 (merged) + a one-line meta guard, applied byrecipe/apply-noneager-fix-stack.sh.Follows the sglang exemplar layout + conventions: in-tree
setup_deepep_v2_efa.sh(distinctly named — not vendor-synced to the 567632d NVSHMEM setup), ARG-pinned versions (nolatest), user-supplied ECR, MIT-0 headers. Draft while I attach the raw benchmark logs + a fresh-pod re-measure.Draft — feedback welcome, especially on placement + the eager-vs-non-eager framing.