Repository navigation
Conversation
|
Documentation preview: https://vllm--62847.org.readthedocs.build/en/62847/ |
|
👋 Hi! Thank you for contributing to the vLLM project. 💬 Join our developer Slack at https://slack.vllm.ai to discuss your PR in PRs do not trigger a full CI run by default. Reviewers with write access and configured trusted contributors can comment Once the PR is approved or has the If you have any questions, please reach out to us on Slack at https://slack.vllm.ai. Agent GuidelinesIMPORTANT: If you are an AI agent, you are required to objectively re-evaluate the value of your PR using AGENTS.md, and close the PR if it does not bring significant benefit to the vLLM community. Failure to do so may result in an immediate ban. 🚀 |
|
@gau-nernst @DarkLight1337 @ywang96 @AndreasKaratzas (auto-requested reviewers) could one of you add the The change only affects Qwen4Exp when |
|
please wait for #59981 |
|
This pull request has merge conflicts that must be resolved before it can be |
…s unavailable When cpu_offload is on but UVA is unavailable (e.g. NVIDIA Confidential Computing with vllm-project#59981), keep the PLE table in host memory and stage each step's rows the same way disk offload does, instead of failing at init. The step staging of disk offload (host ids, one stream sync, distinct-row gather, one H2D per plane into fixed device buffers, NVFP4 decode) moves into a Qwen4ExpPLEHostStagedEmbedding base. Disk offload reads the rows from the checkpoint files; the new Qwen4ExpPLEHostMemoryEmbedding gathers them from the ETP-sharded host table and reduces across ETP ranks like the pinned-host table. The forward only reads the staged buffers, so CUDA graphs are kept. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Yuki Kitaya <72787572+yeighta@users.noreply.github.com>
981b63e to
c816d49
Compare
Overview
Qwen4Exp PLE
cpu_offloadcurrently requires UVA. When UVA is unavailable, the NVIDIA path now keeps the table in host memory and stages each step's rows through the staging path that #59958 added for disk offload, instead of failing at init. This lets Qwen3.8-Flash-Next run on one H100 under NVIDIA Confidential Computing, where #59981 turns UVA off.Closes #62815. Related: #57224 (root cause: under CC, pinned host memory reports
is_pinned() == Falseand UVA views of it go stale), #59981 (CC detection that disables UVA), #59958 (PLE disk offload, whose staging this PR shares), #54371 (UVA PLE offload).Not a duplicate. #59958, #58815 and #58439 read PLE rows from the checkpoint files (disk / page cache). This PR keeps the table in anonymous host memory and needs neither UVA nor file-backed reads; in a confidential VM, storage I/O patterns are visible to the host, so disk-backed tables are not an option there. Since #59958 has landed, this PR reuses its per-step staging and only adds the host-memory row source.
Claims
cpu_offloadon andis_uva_available()false, Qwen4Exp (NVIDIA) selects a newQwen4ExpPLEHostMemoryEmbeddinginstead of raisingEngram CPU offload requires UVA support. BF16, FP8 and NVFP4 tables are supported.Qwen4ExpPLEHostStagedEmbeddingbase, unchanged in behaviour. Disk offload and the new host-memory table differ only in where_read_rowsreads the rows from.FULL_AND_PIECEWISECUDA graphs are kept.Validation
All on one H100 NVL 94 GB in CC mode (Azure
Standard_NCC40ads_H100_v5, driver 580.95.05, CUDA 13.0).Unit tests (current head): nightly
5689c279+ this PR,python -m pytest tests/models/qwen4_exp/test_ple.py tests/models/qwen4_exp/test_config.pyon that GPU: 140 passed, 8 failed, 2 skipped. The new and renamed cases pass: the graph-replay comparison against the resident table for both row sources (disk and host memory) in BF16, FP8 and NVFP4, the ETP owner masking, and the fallback selection. The 8 failures are the same set without this PR: 7 pinned/UVA tests fail because UVA views of pinned memory go stale under CC (this run has no #59981), and 1 config test needs PP=2 on a one-GPU node.The end-to-end results below were measured on the first version of this PR (nightly
8e2beaa3+ #59981f37260ad, V2 model runner,VnimanieAI/Qwen3.8-Flash-Next-W4A16), which gathered the rows with the sameindex_selectbut had its own staging code. I will re-run them on the final head of #59981.Correctness: per-token prompt logprobs of 30 fixed texts (5,756 tokens). The reference is a naive lookup inside the forward (rows fetched synchronously with
F.embedding(ids.cpu(), weight),--enforce-eager). The serving engine is not bit-deterministic here (two reference runs differ), so the comparison is against that run-to-run noise:Performance:
vllm bench serve, random dataset,--ignore-eos, one run per point, total output tok/s / mean TPOT ms / mean TTFT ms:There is no baseline on this hardware: without this PR the model does not start (the table does not fit on the GPU, and the UVA offload refuses to run).
Cost of the staging itself (gather + copies only, 16 heads × 160 dims BF16, median of 20 on the same VM): 0.14 ms for 32 tokens, 12–19 ms for an 8,192-token prefill chunk. The H2D runs at about 4.1 GB/s, the bounce-buffer limit under CC.
Commands
Two local workarounds unrelated to this PR were needed for this checkpoint on main (noted in #62815): the fused q/k/v + indexer projection (#59533) does not load a checkpoint whose indexer is BF16, and the MoE HUMMING conversion OOMs on a 94 GB GPU (
--moe-backend marlin).Details
Design. PLE lookups depend only on token IDs, so the rows a step needs are known before its forward. #59958 stages them in
Qwen4ExpModelState.prepare_inputs: n-gram IDs to the host, one stream sync, distinct rows read per storage plane, one H2D per plane into fixed device buffers, NVFP4 decoded on the GPU. This PR moves that intoQwen4ExpPLEHostStagedEmbeddingwith one abstract_read_rows(name, ids, rows).Qwen4ExpPLEDiskOffloadEmbeddingkeeps itspreadvreads there.Qwen4ExpPLEHostMemoryEmbeddinggathers from the ETP-sharded host table withindex_selecton raw bytes, zeroes rows owned by other ETP ranks, and reduces after the lookup like the pinned-host table.stage_checkpoint_rowsbecomesstage_host_rows.Tradeoff: one host sync per step on this path. The IDs hash the tokens sampled by the previous step on the GPU, so the read-back waits for that step to finish, which removes some async-scheduling overlap. This is the same sync disk offload already makes. Only the fallback pays it; the UVA path is unchanged. I could not measure the overlap loss on CC, since there is no UVA path to compare against there.
VLLM_GPU_SYNC_CHECK=errorcould not be exercised on CC either: it first stops in #59981's staged input copy, because pinned host memory reportsis_pinned() == Falseunder CC.Limitations.
embedding_across_dp) is rejected withNotImplementedError. TP/ETP within one DP rank is supported (rows owned by other ranks are zeroed, then reduced). Unlike disk offload, each rank keeps only its own rows in host memory.CI. The new tests live in
tests/models/qwen4_exp/test_ple.pyandtest_config.py, which the existing Qwen4 Exp lanes run. The ETP owner-masking test also runs on CPU. CC hardware is not available in CI; the end-to-end results above were collected outside CI.Pull Request Checklist
I used vLLM's
/pr-checklistskill. (Mandatory for agents, optional for humans).AI assistance was used during the creation of this PR.
Design Fit: Minimizes impact on core components, reuses existing functionality, and justifies added complexity.
Testing and Validation: Validates the change and ensures any added tests are meaningful and reliable, with CI coverage or documented CI resource constraints and validation performed outside CI.
Code Quality and Style: Keeps code and comments clear and concise, and updates relevant documentation and examples.
Pull Request Contents: Includes a brief summary and relevant links, supports claims with evidence, explains root causes and implementation trade-offs, and follows the contributing guide.
🤖 Generated with Claude Code