forked from foundry-org/foundry
-
Notifications
You must be signed in to change notification settings - Fork 0
[sglang] No-fabric DeepEP EP: port the NVL CUDA-IPC path to the SGLang integration #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
rchalamala
wants to merge
11
commits into
main
Choose a base branch
from
devin/1784752573-sglang-nofabric-ep-ipc
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
848cbe7
[fix] add ep ipc fix, deepep works without nvl_bytes=0
xenshinu bd83ad1
[sglang] add DeepEP no-fabric IPC policy
devin-ai-integration[bot] acb5208
[sglang] add no-fabric DeepEP IPC recipe
devin-ai-integration[bot] e586367
[sglang] fail clearly on old DeepEP API
devin-ai-integration[bot] 0f611cc
[sglang] move inspect import to module top
devin-ai-integration[bot] a064fc7
[sglang] enforce DeepEP use_fabric requirement at Buffer construction
devin-ai-integration[bot] c999763
Make ranked VMM IPC imports deterministic
devin-ai-integration[bot] 52044e5
Reserve one VMM IPC import zone
devin-ai-integration[bot] db05c70
Widen deterministic VMM IPC import slots
devin-ai-integration[bot] 1bec2a7
Import ops wildcard first so Python wrappers win
devin-ai-integration[bot] db3b21c
Default-initialize from_import_zone
devin-ai-integration[bot] File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,156 @@ | ||
| # Foundry recipe — experimental (DeepEP legacy CUDA-IPC NVL buffer) | ||
|
|
||
| End-to-end SAVE / LOAD recipe for **Qwen3-30B-A3B** expert-parallel where DeepEP's | ||
| intranode NVLink buffer stays on the **legacy CUDA-IPC** path | ||
| (`cudaIpcGetMemHandle` / `cudaIpcOpenMemHandle`) under foundry, instead of the | ||
| default fabric/NVSHMEM-only path used by `recipe/vllm/serve_qwen3-30ba3b_ep.sh`. | ||
|
|
||
| This exercises foundry's **VMM-IPC translation layer**: DeepEP's NVL buffer is a | ||
| foundry VMM (`cuMemCreate`) allocation that legacy IPC can't share, so the hook | ||
| exports it as a POSIX fd and transports that fd to the peer rank via | ||
| `SCM_RIGHTS` over a per-process unix socket, then maps it into the importer's | ||
| own VA range. This is the path that lets foundry SAVE/LOAD work on machines | ||
| **without fabric / IMEX**, where DeepEP would otherwise fail at `Buffer.sync` | ||
| with `cuMemImportFromShareableHandle ... error 999`. | ||
|
|
||
| ``` | ||
| recipe/experimental/ | ||
| ├── README.md # this file | ||
| ├── foundry_save.toml # SAVE config (workspace_root = "foundry_archive_ipc") | ||
| ├── foundry_load.toml # LOAD config (same workspace_root) | ||
| ├── serve_qwen3-30ba3b_ipc_ep.sh # Qwen3-30B-A3B (MoE) vLLM EP, NVL/IPC | ||
| ├── sglang_foundry_save.toml # SGLang SAVE config | ||
| ├── sglang_foundry_load.toml # SGLang LOAD config | ||
| └── serve_qwen3-30ba3bfp8_sglang_ipc_ep.sh # SGLang EP, DeepEP NVL/IPC | ||
| ``` | ||
|
|
||
| It is the standard `recipe/vllm` EP recipe plus one switch — `FOUNDRY_DEEPEP_NVL_IPC=1` | ||
| — so read [`../vllm/README.md`](../vllm/README.md) first for installation, the | ||
| two-pass SAVE workflow, the archive layout, and the shared EP flags. Only the | ||
| IPC-specific deltas are documented here. | ||
|
|
||
| ## Required code | ||
|
|
||
| The IPC path needs only **Foundry** changes beyond the standard install — no | ||
| vLLM edit: | ||
|
|
||
| - **Foundry** — `foundry/csrc/hook.cpp`: the SCM_RIGHTS VMM-IPC fd transport + | ||
| whole-chunk peer mapping (handles LOAD-mode buffers carved from the | ||
| preallocated chunk). **C++ change → rebuild required:** | ||
| `uv pip install -e . --no-build-isolation` in `foundry/`. | ||
| - **Foundry** — `foundry/python/foundry/integration/vllm/hooks.py`: the | ||
| `FOUNDRY_DEEPEP_NVL_IPC` env knob in `_patch_deepep` (Python, no rebuild). | ||
| - **Foundry** — `foundry/python/foundry/integration/sglang/hooks.py`: the | ||
| matching SGLang `deep_ep.Buffer` policy patch (Python, no rebuild). | ||
|
|
||
| ### Run all phases from one consistent path (no vLLM edit needed) | ||
|
|
||
| vLLM folds the foundry TOML path (`graph_extension_config_path`) into its | ||
| torch.compile cache key even though the path never affects codegen. If SAVE | ||
| pass 1 and pass 2 see that path with *different spellings* — e.g. two mount | ||
| aliases of the same dir (`/data/...` vs `/home/...`), or you move the TOML | ||
| between passes — pass 2 misses pass 1's warm compile cache and inductor | ||
| recompiles **inside** the cuda-graph capture window, where its combo-kernel | ||
| benchmark does an illegal `torch.randn` → `cudaErrorStreamCaptureInvalidated`. | ||
|
|
||
| The fix is operational, not code: **invoke the script the same way for every | ||
| phase** (same shell / same `cd`, or always an absolute path), so SAVE pass 1, | ||
| SAVE pass 2, and LOAD all pass the identical path string → identical cache hash | ||
| → pass 2 reuses pass 1's compiled kernels. Run from the workspace root, e.g.: | ||
|
|
||
| ```bash | ||
| cd <workspace> # one canonical path for all three phases | ||
| bash foundry/recipe/experimental/serve_qwen3-30ba3b_ipc_ep.sh 2 --save | ||
| bash foundry/recipe/experimental/serve_qwen3-30ba3b_ipc_ep.sh 2 --save | ||
| bash foundry/recipe/experimental/serve_qwen3-30ba3b_ipc_ep.sh 2 --load | ||
| ``` | ||
|
|
||
| ## Workflow | ||
|
|
||
| Same two-pass SAVE → LOAD as the base recipe; `<ep_size>` is the first arg: | ||
|
|
||
| ```bash | ||
| # 0. Fresh start (distinct workspace from the base recipe) | ||
| rm -rf foundry_archive_ipc | ||
|
|
||
| # 1. SAVE pass 1 — memory profile + capture | ||
| bash serve_qwen3-30ba3b_ipc_ep.sh 2 --save | ||
| # wait for "Application startup complete", then Ctrl-C | ||
|
|
||
| # 2. SAVE pass 2 — deterministic re-capture | ||
| bash serve_qwen3-30ba3b_ipc_ep.sh 2 --save | ||
| # wait for "Application startup complete", then Ctrl-C | ||
|
|
||
| # 3. LOAD — preallocate, re-import IPC buffers, replay graphs | ||
| bash serve_qwen3-30ba3b_ipc_ep.sh 2 --load | ||
| # leave running | ||
|
|
||
| # 4. Query (separate shell) | ||
| bash ../../../experimental/query.sh 12000 Qwen/Qwen3-30B-A3B | ||
| ``` | ||
|
|
||
| Uncomment `nvshmem_host_path` in both TOMLs first (EP still needs NVSHMEM for the | ||
| DeepEP RDMA buffer; the IPC path only changes the NVL buffer). | ||
|
|
||
| ## SGLang variant | ||
|
|
||
| The SGLang variant is | ||
| `serve_qwen3-30ba3bfp8_sglang_ipc_ep.sh`. It uses the same Foundry VMM-IPC core | ||
| but the SGLang integration wraps `deep_ep.Buffer.__init__` rather than vLLM's | ||
| all-to-all kwargs builder. Use the SGLang-specific TOMLs and run the same | ||
| `--save`/`--load` settings for every phase: | ||
|
|
||
| ```bash | ||
| rm -rf foundry_archive_sglang_ipc | ||
| bash serve_qwen3-30ba3bfp8_sglang_ipc_ep.sh 2 --save | ||
| bash serve_qwen3-30ba3bfp8_sglang_ipc_ep.sh 2 --load | ||
| ``` | ||
|
|
||
| The SGLang variant requires DeepEP `29d31c0` or newer. This is the vLLM | ||
| installer's validated revision and is API-compatible with SGLang's older | ||
| `Buffer(group, num_nvl_bytes, num_rdma_bytes, ...)` call shape while adding | ||
| `use_fabric`. NVSHMEM remains required for DeepEP's RDMA symmetric heap; only | ||
| the NVL buffer uses CUDA IPC. Keep the model, EP size, low-latency token cap, | ||
| chunked-prefill size, and IPC environment settings identical between SAVE and | ||
| LOAD. | ||
|
|
||
| ## What `FOUNDRY_DEEPEP_NVL_IPC=1` does | ||
|
|
||
| `_patch_deepep` (`foundry/python/foundry/integration/vllm/hooks.py`) normally | ||
| forces `use_fabric=True, num_nvl_bytes=0` so the only cross-GPU buffer is the | ||
| NVSHMEM symmetric heap. With `FOUNDRY_DEEPEP_NVL_IPC=1` it instead keeps | ||
| upstream's nonzero `num_nvl_bytes` with `use_fabric=False`, so the DeepEP Buffer | ||
| allocates the NVLink buffer via `cudaMalloc` + `cudaIpcGetMemHandle` on **both** | ||
| SAVE and LOAD. The hook then: | ||
|
|
||
| - **SAVE**: exports each VMM-backed NVL buffer as a POSIX fd, served to peers | ||
| over `\0foundry-vmm-ipc.<pid>` via `SCM_RIGHTS` (same-uid `SO_PEERCRED` check, | ||
| per-process token vs PID reuse). | ||
| - **LOAD**: buffers are carved from the preallocated chunk (no individual | ||
| handle), so the hook exports the **whole chunk** fd + offset; the peer maps the | ||
| entire chunk once and returns an interior pointer. | ||
| - Peer mappings land at a **relocated** VA (logged `[HOOK] INFO: VMM-IPC import | ||
| relocated`) — correct, because DeepEP resolves peers through its device-side | ||
| `buffer_ptrs_gpu` table (refreshed by `Buffer.sync`), never through addresses | ||
| baked into captured graphs. | ||
|
|
||
| A healthy run logs two `VMM-IPC import relocated` lines per phase (one per peer) | ||
| and **no** `error 999`. | ||
|
|
||
| ## Validation status | ||
|
|
||
| SAVE → SAVE → LOAD → query verified on Qwen3-30B-A3B EP=2 (2× H200, no IMEX): | ||
| per-rank `final_alloc_offset` identical across passes, LOAD replays at the saved | ||
| offset, query returns coherent completions. LOAD reaches a serving server in | ||
| ~27 s; the IPC import itself is sub-second (inside the ~7.5 s `load_model`) and | ||
| has no steady-state serving cost — peer addresses are resolved once at init via | ||
| the device pointer table, not per token. | ||
|
|
||
| ## IPC-specific troubleshooting | ||
|
|
||
| | Symptom | Likely cause | | ||
| |---|---| | ||
| | `[HOOK] ERROR: cuMemImportFromShareableHandle failed with error 999` at `deep_ep.cpp` `Buffer::sync` | Foundry hook not rebuilt with the SCM_RIGHTS transport — it's still packing a raw fd. Rebuild `foundry/` (`uv pip install -e . --no-build-isolation`). | | ||
| | `operation failed due to a previous error during capture` on SAVE **pass 2** | vLLM compile-cache over-keying not applied (`graph_extension_config_path` still hashed) → recompile-in-capture. Apply the `compilation.py` `ignored_factors` edit, or set `FOUNDRY_DISABLE_COMBO_KERNELS=1` (opt-in belt-and-suspenders, wired in the experimental serve script under `experimental/expert-parallel/`). | | ||
| | LOAD `illegal memory access` at replay with an NVL buffer present | Relocated peer import collided with the NVSHMEM heap hint — ensure the hook build includes the dedicated import-VA zone (`0x300000000000`). | | ||
| | `error 999` only with `--deepep-mode auto`/`normal` | That's expected for non-LL modes here; this recipe pins `deepep_low_latency`. | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| mode = "load" | ||
| base_addr = 0x600000000000 | ||
| region_size = "256GB" | ||
| workspace_root = "foundry_archive_ipc" | ||
| scratch_space_size = "4096MB" | ||
| # REQUIRED for the EP/IPC recipe — DeepEP low-latency still allocates its RDMA | ||
| # buffer on the NVSHMEM symmetric heap (the NVL buffer is the cudaIpc path). | ||
| # Point this at the libnvshmem_host.so built by vllm/tools/ep_kernels. | ||
| nvshmem_host_path = "/data/liuxs/workarea/foundry-org/vllm/tools/ep_kernels/ep_kernels_workspace/nvshmem/lib/libnvshmem_host.so" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| mode = "load" | ||
| base_addr = 0x600000000000 | ||
| region_size = "256GB" | ||
| workspace_root = "foundry_archive_ipc_fp8" | ||
| scratch_space_size = "4096MB" | ||
| nvshmem_host_path = "/data/liuxs/workarea/foundry-org/vllm/tools/ep_kernels/ep_kernels_workspace/nvshmem/lib/libnvshmem_host.so" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| mode = "save" | ||
| base_addr = 0x600000000000 | ||
| region_size = "256GB" | ||
| workspace_root = "foundry_archive_ipc" | ||
| scratch_space_size = "4096MB" | ||
| # REQUIRED for the EP/IPC recipe — DeepEP low-latency still allocates its RDMA | ||
| # buffer on the NVSHMEM symmetric heap (the NVL buffer is the cudaIpc path). | ||
| # Point this at the libnvshmem_host.so built by vllm/tools/ep_kernels. | ||
| nvshmem_host_path = "/data/liuxs/workarea/foundry-org/vllm/tools/ep_kernels/ep_kernels_workspace/nvshmem/lib/libnvshmem_host.so" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| mode = "save" | ||
| base_addr = 0x600000000000 | ||
| region_size = "256GB" | ||
| workspace_root = "foundry_archive_ipc_fp8" | ||
| scratch_space_size = "4096MB" | ||
| nvshmem_host_path = "/data/liuxs/workarea/foundry-org/vllm/tools/ep_kernels/ep_kernels_workspace/nvshmem/lib/libnvshmem_host.so" |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.