Repository navigation
Optimize tensor parallel execution speed - #17
Merged
Merged
Conversation
WoosukKwon
approved these changes
Mar 31, 2023
WoosukKwon
left a comment
Collaborator
There was a problem hiding this comment.
Awesome! Thanks for the effort.
WoosukKwon
reviewed
Mar 31, 2023
hongxiayang
pushed a commit
to hongxiayang/vllm
that referenced
this pull request
Feb 13, 2024
AdrianAbeyta
referenced
this pull request
in ROCm/vllm
Mar 8, 2024
Rebase fp8_kv branch with upstream (3-07-2024)
z103cb
referenced
this pull request
in z103cb/opendatahub_vllm
Apr 22, 2024
These Dockerfile changes: - Update the release stage to work with the recently refactored `requirements-common.txt` / `requirements-cuda.txt` split - Fixup the kernel compilation in the `build` stage to correctly pick up cuda - Install the kernels from this docker build rather than pulling a precompiled wheel. We can swap that back once a new wheel is available with the correct pytorch version + updated interfaces --------- Signed-off-by: Nick Hill <nickhill@us.ibm.com> Signed-off-by: Joe Runde <Joseph.Runde@ibm.com> Co-authored-by: Joe Runde <Joseph.Runde@ibm.com>
fxmarty
pushed a commit
to fxmarty/vllm-public
that referenced
this pull request
May 31, 2024
[ROCm] adding a missing triton autotune config
Closed
1 task done
wuhuikx
pushed a commit
to wuhuikx/vllm
that referenced
this pull request
Mar 27, 2025
### What this PR does / why we need it? Add dispatch key for NPU, so that the log could be print correctly. Now ``` executor_base.py:110] # CPU blocks: 220478, # CPU blocks: 21845 ``` After this pr ``` executor_base.py:110] # NPU blocks: 220478, # CPU blocks: 21845 ``` ### Does this PR introduce _any_ user-facing change? N/A ### How was this patch tested? CI passed and log printed as above Signed-off-by: MengqingCao <cmq0113@163.com>
1 task done
1 task done
1 task done
robertgshaw2-redhat
added a commit
that referenced
this pull request
Jul 7, 2025
Load balance across multiple workers
1 task done
zyongye
pushed a commit
to zyongye/vllm
that referenced
this pull request
Aug 5, 2025
zyongye
pushed a commit
to zyongye/vllm
that referenced
this pull request
Aug 6, 2025
1 task done
heheda12345
added a commit
to heheda12345/vllm
that referenced
this pull request
Sep 29, 2025
* prefill mla Signed-off-by: Chen Zhang <zhangch99@outlook.com> * can run now Signed-off-by: Chen Zhang <zhangch99@outlook.com> * tmp Signed-off-by: Chen Zhang <zhangch99@outlook.com> * can output the first token Signed-off-by: Chen Zhang <zhangch99@outlook.com> * fix bug Signed-off-by: Chen Zhang <zhangch99@outlook.com> * remove some debug Signed-off-by: Chen Zhang <zhangch99@outlook.com> * update Signed-off-by: Chen Zhang <zhangch99@outlook.com> * hack through cu_seqlen_ks exploding issue * update basic.py Signed-off-by: Chen Zhang <zhangch99@outlook.com> * remove some unnecessary changes Signed-off-by: Chen Zhang <zhangch99@outlook.com> * clean up Signed-off-by: Chen Zhang <zhangch99@outlook.com> --------- Signed-off-by: Chen Zhang <zhangch99@outlook.com> Co-authored-by: Yongye Zhu <zyy1102000@gmail.com>
1 task done
4 tasks
heliubj18
added a commit
to heliubj18/vllm
that referenced
this pull request
Aug 8, 2026
401 of the step's 402 cases need no device, but test_scheduler.py::test_async_scheduling_pp_allows_rescheduling_with_output_placeholders builds a ParallelConfig with pipeline_parallel_size=2. It never touches a second card - the step allocates 0.0 GiB across its whole run - but on a CUDA image ParallelConfig validates world size against the visible GPU count and rejects 2. Upstream never sees this: the step depends on image-build-cpu, where that check is inert. So the marking upstream gives a step describes the image it runs on, not what its cases ask for, and _gpus_for() had no way to say otherwise. Adds docker.devices_by_step, a per-key override of the device count that indexes into the existing gpus_by_devices map. Only v1-others-cpu uses it; the generated pipeline differs from before by exactly one line, and the other CPU-marked steps still get "device=0". Two cards costs nothing when the step allocates no VRAM, and leaving it at one meant a guaranteed failure every run - which is expensive now that fail_fast is back on. In vllm-project#24 it cancelled Basic Models Test and Torch Stable ABI Audit, both of which pass (3m19s in vllm-project#17). I had written this case off as "not worth handling" without accounting for that. Co-authored-by: Claude Opus 5
davetha
added a commit
to davetha/vllm
that referenced
this pull request
Aug 15, 2026
Adds TritonNvFp4LinearKernel: dequantizes packed e2m1 weights (2 codes per uint8 byte, low-nibble-first, per-16-group e4m3 block scale, scalar global scale) directly in the GEMM inner loop and consumes bf16/fp16 activations unquantized -- the W4A16 weight-only path used by nvfp4-pack-quantized compressed-tensors checkpoints (e.g. huginnfork/Qwen3.8-27B-NVFP4A16, whose config.json has input_activations: null) and ModelOpt's W4A16_NVFP4 quant_method. The decode math is ported from the standalone prototype/benchmark that measured it (nvfp4_final.py, fp8-decode's vllm-project#19 pass: correct on a synthetic K=512,N=256 sweep, ~3.5 decode ops/weight, 2.26x wall-clock over an Emulation-style dequant+matmul baseline on gate_up-shaped data), not re-derived. Two things needed changing to productize it and are NOT yet GPU-verified in this form, flagged inline in the new file: - Packing layout: the prototype's synthetic test data packs 8 e2m1 codes per int32. Real checkpoints pack 2 codes per uint8 byte along K, confirmed against torch.float4_e2m1fn_x2's own unpack convention. The unpack is rewritten for byte-pair packing; the bit-shift E2M1 decode, the fp16-subnormal-flush defense (gfx90a's MFMA flushes subnormal inputs to zero, same finding as the FP8 W8A16 kernel, 2**14 fold here vs that kernel's 2**8), and the two-stage scale fold are unchanged from the validated prototype. - weight_global_scale: the prototype's harness had no global scale (its synthetic data didn't model one). Real NVFP4 checkpoints do; added as a third fp32 epilogue multiply, not present in the validated prototype. Also fixes the dispatcher landmine that blocked ANY weight-only NVFP4 on ROCm regardless of what's registered in _POSSIBLE_NVFP4_KERNELS: init_nvfp4_linear_kernel's linear_backend=="auto" and use_a16 branch force-selected MarlinNvFp4LinearKernel unconditionally, with no platform check, and raised (Marlin is CUDA-only) before the function ever reached the registry search below it. Same class of bug as d74ce3d's CUDA-shaped capability check, just in the NVFP4 dispatcher instead of the FP8 scheme-selection path. Gated the force on current_platform.is_cuda() so other platforms fall through to their own registry entry. TritonNvFp4LinearKernel is added to both _POSSIBLE_NVFP4_KERNELS[ROCM] (ahead of EmulationNvFp4LinearKernel) and the separate a16_kernels tuple in init_nvfp4_linear_kernel -- registering in only one silently drops the kernel from use_a16=True requests via the other's filter. Gated strictly to gfx90a via on_gfx90a(), same as TritonW8A16Fp8LinearKernel: the subnormal-flush workaround and any future tile-ladder tuning are measured facts about this card, not proven elsewhere. NOT YET RUN ON GPU. Per team sequencing the card is currently occupied by the FP8 pipeline (e2e battery, vllm-project#17 benchmark, fp8-impl's ladder measurements); this lands as a reviewable, buildable artifact for its own verification pass once cleared, by someone other than its author. Does not ship in the FP8 PRs -- separate verification cycle, separate PR. MXFP4 is the natural follow-on (E8M0 per-32 scales instead of e4m3 per-16, cheaper decode -- E8M0 dequant is a pure exponent add, no mantissa/sign bits at all -- gpt-oss checkpoint format) but is intentionally not implemented here; ROCm already has a non-emulation MXFP4 backend via AiterMxfp4LinearKernel, gated off on this card only by supports_mx() excluding gfx90a, and MXFP4's own init_mxfp4_linear_kernel has no analogous CUDA-hardcoded force to fix -- a smaller, separate task.
grYe99
pushed a commit
to grYe99/vllm
that referenced
this pull request
Sep 17, 2026
ci: build vLLM on a self-hosted CN runner
zankich
added a commit
to zankich/vllm
that referenced
this pull request
Sep 24, 2026
…ive reader Counts K/V elements that would saturate E4M3 after scaling. The increments are pure tensor ops inside the forward, safe under capture by construction. Reading happens only where concurrency cannot exist: VLLM_QSA_KV_CLIP_COUNT arms the counters and drains per-layer totals once at engine shutdown on the engine's own thread; VLLM_QSA_KV_CLIP_READER additionally runs the live reader thread, diagnostic-only under --enforce-eager. The reader constraint is architectural, established across four engine-killing failure modes, each the next CUDA rule a concurrent thread violates during graph capture: sync reads (halt95 issue vllm-project#17), pinned-host allocation, stream creation draining the device, and event queries — all illegal or hazardous during capture, and no API exposes capture state to another thread. halt95's rc3-rc7 patch arc (non-blocking mirrors, 0071) reached the same conclusion and their 0073 operator ruling shipped readers off; this design ports that ruling. Tests drive _qsa_clip_count as production does, arming under inference_mode and asserting the drained world. Co-authored-by: Claude <noreply@anthropic.com> Signed-off-by: Adrian Zankich <adzankich@gmail.com>
leapdragon
added a commit
to leapdragon/vllm-rdna2-qwen
that referenced
this pull request
Sep 26, 2026
…e outbound transfer per card per round Replaces the grouped all-to-all (each card receiving from all three peers at once), which every V620 bus drop since 09-25 had enabled. Bit-identical results; 1.02-1.15x faster on 4x V620 (q8_ar_test.py). VLLM_RDNA_AR_Q8_STAGGER=0 restores the old exchange. CHANGES vllm-project#17. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
5 of 6 tasks
zankich
added a commit
to zankich/vllm
that referenced
this pull request
Oct 3, 2026
…ive reader Counts K/V elements that would saturate E4M3 after scaling. The increments are pure tensor ops inside the forward, safe under capture by construction. Reading happens only where concurrency cannot exist: VLLM_QSA_KV_CLIP_COUNT arms the counters and drains per-layer totals once at engine shutdown on the engine's own thread; VLLM_QSA_KV_CLIP_READER additionally runs the live reader thread, diagnostic-only under --enforce-eager. The reader constraint is architectural, established across four engine-killing failure modes, each the next CUDA rule a concurrent thread violates during graph capture: sync reads (halt95 issue vllm-project#17), pinned-host allocation, stream creation draining the device, and event queries — all illegal or hazardous during capture, and no API exposes capture state to another thread. halt95's rc3-rc7 patch arc (non-blocking mirrors, 0071) reached the same conclusion and their 0073 operator ruling shipped readers off; this design ports that ruling. Tests drive _qsa_clip_count as production does, arming under inference_mode and asserting the drained world. Co-authored-by: Claude <noreply@anthropic.com> Signed-off-by: Adrian Zankich <adzankich@gmail.com>
YukioZzz
pushed a commit
to YukioZzz/vllm
that referenced
this pull request
Oct 16, 2026
[Step5] Require Model Runner V2 and drop the V1 runner changes
1 task done
Chloe-orz
pushed a commit
to Chloe-orz/vllm-maintomain
that referenced
this pull request
Oct 26, 2026
…plane [Feature][Lwd] Build the edge-cloud parallel groups from the LWD topology without two-stage PP
2 of 6 tasks
KexyBiscuit
pushed a commit
to tai-core/vllm-tracking
that referenced
this pull request
Nov 4, 2026
vllm-project#17) Keep fixed-ring KPool tail state out of context-length token slot mapping. Retain dedicated tail writes and add boundary regression tooling for chunked prefill. Preserve the reviewed source tree from PR vllm-project#17; the squash only reorganizes Git history. Existing acceptance evidence and remaining limitations are recorded in overview PR vllm-project#11. No new model tests were run for this integration. Original-PR-Head: cc3ea839105a676b1071e377b3cd61c0427c2d47 Assisted-by: Codex
KexyBiscuit
pushed a commit
to tai-core/vllm-tracking
that referenced
this pull request
Nov 4, 2026
The grouped-GEMM permute (ep_scatter) launched one program per token and let every
thread of the block redo the same 8 scalar top-k lookups, so a layer paid ~375 us per
permute at 8k tokens while only ~30 us of that was actual row movement. ep_gather had
the same shape problem (one program per hidden chunk and token block, with a token
loop inside).
These kernels are the MUSA implementation of the permute/gather, selected through
current_platform.is_musa() like the other MUSA paths in this fork:
* route pairs with a 64-token tile so the top-k loads coalesce and the destination
atomics are issued as vectors;
* compute the per-expert start offsets on the device instead of with torch ops;
* copy the activation row together with its block scales in one kernel, driven by a
compact source-row map, so the scatter is a plain vectorised row copy;
* gather with one program per (token, hidden chunk) and a static top-k loop.
Measured on 8x MTT S5000, GLM-5.3-Flash, TP1 + PCP8 + EP8, 128 prompts x 8192 in:
permute 375 -> 120 us (3.1x), gather 128 -> 119 us (1.07x, bitwise identical)
end to end 16,744 -> 17,302 tok/s (+3.3%), median TTFT 30.99 -> 29.98 s
Correctness: every routed pair was compared against the stock kernel (activation
row, scales and m_indices all match) and greedy generation is token-identical to the
baseline (5/5 prompts, max |d mean logprob| = 5.35e-3).
Other platforms keep the existing kernels unchanged.
KexyBiscuit
pushed a commit
to tai-core/vllm-tracking
that referenced
this pull request
Nov 4, 2026
vllm-project#17) Keep fixed-ring KPool tail state out of context-length token slot mapping. Retain dedicated tail writes and add boundary regression tooling for chunked prefill. Preserve the reviewed source tree from PR vllm-project#17; the squash only reorganizes Git history. Existing acceptance evidence and remaining limitations are recorded in overview PR vllm-project#11. No new model tests were run for this integration. Original-PR-Head: cc3ea839105a676b1071e377b3cd61c0427c2d47 Assisted-by: Codex
KexyBiscuit
pushed a commit
to tai-core/vllm-tracking
that referenced
this pull request
Nov 4, 2026
The grouped-GEMM permute (ep_scatter) launched one program per token and let every
thread of the block redo the same 8 scalar top-k lookups, so a layer paid ~375 us per
permute at 8k tokens while only ~30 us of that was actual row movement. ep_gather had
the same shape problem (one program per hidden chunk and token block, with a token
loop inside).
These kernels are the MUSA implementation of the permute/gather, selected through
current_platform.is_musa() like the other MUSA paths in this fork:
* route pairs with a 64-token tile so the top-k loads coalesce and the destination
atomics are issued as vectors;
* compute the per-expert start offsets on the device instead of with torch ops;
* copy the activation row together with its block scales in one kernel, driven by a
compact source-row map, so the scatter is a plain vectorised row copy;
* gather with one program per (token, hidden chunk) and a static top-k loop.
Measured on 8x MTT S5000, GLM-5.3-Flash, TP1 + PCP8 + EP8, 128 prompts x 8192 in:
permute 375 -> 120 us (3.1x), gather 128 -> 119 us (1.07x, bitwise identical)
end to end 16,744 -> 17,302 tok/s (+3.3%), median TTFT 30.99 -> 29.98 s
Correctness: every routed pair was compared against the stock kernel (activation
row, scales and m_indices all match) and greedy generation is token-identical to the
baseline (5/5 prompts, max |d mean logprob| = 5.35e-3).
Other platforms keep the existing kernels unchanged.
KexyBiscuit
pushed a commit
to tai-core/vllm-tracking
that referenced
this pull request
Nov 4, 2026
vllm-project#17) Keep fixed-ring KPool tail state out of context-length token slot mapping. Retain dedicated tail writes and add boundary regression tooling for chunked prefill. Preserve the reviewed source tree from PR vllm-project#17; the squash only reorganizes Git history. Existing acceptance evidence and remaining limitations are recorded in overview PR vllm-project#11. No new model tests were run for this integration. Original-PR-Head: cc3ea839105a676b1071e377b3cd61c0427c2d47 Assisted-by: Codex
KexyBiscuit
pushed a commit
to tai-core/vllm-tracking
that referenced
this pull request
Nov 4, 2026
The grouped-GEMM permute (ep_scatter) launched one program per token and let every
thread of the block redo the same 8 scalar top-k lookups, so a layer paid ~375 us per
permute at 8k tokens while only ~30 us of that was actual row movement. ep_gather had
the same shape problem (one program per hidden chunk and token block, with a token
loop inside).
These kernels are the MUSA implementation of the permute/gather, selected through
current_platform.is_musa() like the other MUSA paths in this fork:
* route pairs with a 64-token tile so the top-k loads coalesce and the destination
atomics are issued as vectors;
* compute the per-expert start offsets on the device instead of with torch ops;
* copy the activation row together with its block scales in one kernel, driven by a
compact source-row map, so the scatter is a plain vectorised row copy;
* gather with one program per (token, hidden chunk) and a static top-k loop.
Measured on 8x MTT S5000, GLM-5.3-Flash, TP1 + PCP8 + EP8, 128 prompts x 8192 in:
permute 375 -> 120 us (3.1x), gather 128 -> 119 us (1.07x, bitwise identical)
end to end 16,744 -> 17,302 tok/s (+3.3%), median TTFT 30.99 -> 29.98 s
Correctness: every routed pair was compared against the stock kernel (activation
row, scales and m_indices all match) and greedy generation is token-identical to the
baseline (5/5 prompts, max |d mean logprob| = 5.35e-3).
Other platforms keep the existing kernels unchanged.
KexyBiscuit
pushed a commit
to tai-core/vllm-tracking
that referenced
this pull request
Nov 5, 2026
The grouped-GEMM permute (ep_scatter) launched one program per token and let every
thread of the block redo the same 8 scalar top-k lookups, so a layer paid ~375 us per
permute at 8k tokens while only ~30 us of that was actual row movement. ep_gather had
the same shape problem (one program per hidden chunk and token block, with a token
loop inside).
These kernels are the MUSA implementation of the permute/gather, selected through
current_platform.is_musa() like the other MUSA paths in this fork:
* route pairs with a 64-token tile so the top-k loads coalesce and the destination
atomics are issued as vectors;
* compute the per-expert start offsets on the device instead of with torch ops;
* copy the activation row together with its block scales in one kernel, driven by a
compact source-row map, so the scatter is a plain vectorised row copy;
* gather with one program per (token, hidden chunk) and a static top-k loop.
Measured on 8x MTT S5000, GLM-5.3-Flash, TP1 + PCP8 + EP8, 128 prompts x 8192 in:
permute 375 -> 120 us (3.1x), gather 128 -> 119 us (1.07x, bitwise identical)
end to end 16,744 -> 17,302 tok/s (+3.3%), median TTFT 30.99 -> 29.98 s
Correctness: every routed pair was compared against the stock kernel (activation
row, scales and m_indices all match) and greedy generation is token-identical to the
baseline (5/5 prompts, max |d mean logprob| = 5.35e-3).
Other platforms keep the existing kernels unchanged.
KexyBiscuit
pushed a commit
to tai-core/vllm-tracking
that referenced
this pull request
Nov 5, 2026
The grouped-GEMM permute (ep_scatter) launched one program per token and let every
thread of the block redo the same 8 scalar top-k lookups, so a layer paid ~375 us per
permute at 8k tokens while only ~30 us of that was actual row movement. ep_gather had
the same shape problem (one program per hidden chunk and token block, with a token
loop inside).
These kernels are the MUSA implementation of the permute/gather, selected through
current_platform.is_musa() like the other MUSA paths in this fork:
* route pairs with a 64-token tile so the top-k loads coalesce and the destination
atomics are issued as vectors;
* compute the per-expert start offsets on the device instead of with torch ops;
* copy the activation row together with its block scales in one kernel, driven by a
compact source-row map, so the scatter is a plain vectorised row copy;
* gather with one program per (token, hidden chunk) and a static top-k loop.
Measured on 8x MTT S5000, GLM-5.3-Flash, TP1 + PCP8 + EP8, 128 prompts x 8192 in:
permute 375 -> 120 us (3.1x), gather 128 -> 119 us (1.07x, bitwise identical)
end to end 16,744 -> 17,302 tok/s (+3.3%), median TTFT 30.99 -> 29.98 s
Correctness: every routed pair was compared against the stock kernel (activation
row, scales and m_indices all match) and greedy generation is token-identical to the
baseline (5/5 prompts, max |d mean logprob| = 5.35e-3).
Other platforms keep the existing kernels unchanged.
KexyBiscuit
pushed a commit
to tai-core/vllm-tracking
that referenced
this pull request
Nov 5, 2026
The grouped-GEMM permute (ep_scatter) launched one program per token and let every
thread of the block redo the same 8 scalar top-k lookups, so a layer paid ~375 us per
permute at 8k tokens while only ~30 us of that was actual row movement. ep_gather had
the same shape problem (one program per hidden chunk and token block, with a token
loop inside).
These kernels are the MUSA implementation of the permute/gather, selected through
current_platform.is_musa() like the other MUSA paths in this fork:
* route pairs with a 64-token tile so the top-k loads coalesce and the destination
atomics are issued as vectors;
* compute the per-expert start offsets on the device instead of with torch ops;
* copy the activation row together with its block scales in one kernel, driven by a
compact source-row map, so the scatter is a plain vectorised row copy;
* gather with one program per (token, hidden chunk) and a static top-k loop.
Measured on 8x MTT S5000, GLM-5.3-Flash, TP1 + PCP8 + EP8, 128 prompts x 8192 in:
permute 375 -> 120 us (3.1x), gather 128 -> 119 us (1.07x, bitwise identical)
end to end 16,744 -> 17,302 tok/s (+3.3%), median TTFT 30.99 -> 29.98 s
Correctness: every routed pair was compared against the stock kernel (activation
row, scales and m_indices all match) and greedy generation is token-identical to the
baseline (5/5 prompts, max |d mean logprob| = 5.35e-3).
Other platforms keep the existing kernels unchanged.
KexyBiscuit
pushed a commit
to tai-core/vllm-tracking
that referenced
this pull request
Nov 5, 2026
The grouped-GEMM permute (ep_scatter) launched one program per token and let every
thread of the block redo the same 8 scalar top-k lookups, so a layer paid ~375 us per
permute at 8k tokens while only ~30 us of that was actual row movement. ep_gather had
the same shape problem (one program per hidden chunk and token block, with a token
loop inside).
These kernels are the MUSA implementation of the permute/gather, selected through
current_platform.is_musa() like the other MUSA paths in this fork:
* route pairs with a 64-token tile so the top-k loads coalesce and the destination
atomics are issued as vectors;
* compute the per-expert start offsets on the device instead of with torch ops;
* copy the activation row together with its block scales in one kernel, driven by a
compact source-row map, so the scatter is a plain vectorised row copy;
* gather with one program per (token, hidden chunk) and a static top-k loop.
Measured on 8x MTT S5000, GLM-5.3-Flash, TP1 + PCP8 + EP8, 128 prompts x 8192 in:
permute 375 -> 120 us (3.1x), gather 128 -> 119 us (1.07x, bitwise identical)
end to end 16,744 -> 17,302 tok/s (+3.3%), median TTFT 30.99 -> 29.98 s
Correctness: every routed pair was compared against the stock kernel (activation
row, scales and m_indices all match) and greedy generation is token-identical to the
baseline (5/5 prompts, max |d mean logprob| = 5.35e-3).
Other platforms keep the existing kernels unchanged.
KexyBiscuit
pushed a commit
to tai-core/vllm-tracking
that referenced
this pull request
Nov 5, 2026
The grouped-GEMM permute (ep_scatter) launched one program per token and let every
thread of the block redo the same 8 scalar top-k lookups, so a layer paid ~375 us per
permute at 8k tokens while only ~30 us of that was actual row movement. ep_gather had
the same shape problem (one program per hidden chunk and token block, with a token
loop inside).
These kernels are the MUSA implementation of the permute/gather, selected through
current_platform.is_musa() like the other MUSA paths in this fork:
* route pairs with a 64-token tile so the top-k loads coalesce and the destination
atomics are issued as vectors;
* compute the per-expert start offsets on the device instead of with torch ops;
* copy the activation row together with its block scales in one kernel, driven by a
compact source-row map, so the scatter is a plain vectorised row copy;
* gather with one program per (token, hidden chunk) and a static top-k loop.
Measured on 8x MTT S5000, GLM-5.3-Flash, TP1 + PCP8 + EP8, 128 prompts x 8192 in:
permute 375 -> 120 us (3.1x), gather 128 -> 119 us (1.07x, bitwise identical)
end to end 16,744 -> 17,302 tok/s (+3.3%), median TTFT 30.99 -> 29.98 s
Correctness: every routed pair was compared against the stock kernel (activation
row, scales and m_indices all match) and greedy generation is token-identical to the
baseline (5/5 prompts, max |d mean logprob| = 5.35e-3).
Other platforms keep the existing kernels unchanged.
KexyBiscuit
pushed a commit
to tai-core/vllm-tracking
that referenced
this pull request
Nov 5, 2026
The grouped-GEMM permute (ep_scatter) launched one program per token and let every
thread of the block redo the same 8 scalar top-k lookups, so a layer paid ~375 us per
permute at 8k tokens while only ~30 us of that was actual row movement. ep_gather had
the same shape problem (one program per hidden chunk and token block, with a token
loop inside).
These kernels are the MUSA implementation of the permute/gather, selected through
current_platform.is_musa() like the other MUSA paths in this fork:
* route pairs with a 64-token tile so the top-k loads coalesce and the destination
atomics are issued as vectors;
* compute the per-expert start offsets on the device instead of with torch ops;
* copy the activation row together with its block scales in one kernel, driven by a
compact source-row map, so the scatter is a plain vectorised row copy;
* gather with one program per (token, hidden chunk) and a static top-k loop.
Measured on 8x MTT S5000, GLM-5.3-Flash, TP1 + PCP8 + EP8, 128 prompts x 8192 in:
permute 375 -> 120 us (3.1x), gather 128 -> 119 us (1.07x, bitwise identical)
end to end 16,744 -> 17,302 tok/s (+3.3%), median TTFT 30.99 -> 29.98 s
Correctness: every routed pair was compared against the stock kernel (activation
row, scales and m_indices all match) and greedy generation is token-identical to the
baseline (5/5 prompts, max |d mean logprob| = 5.35e-3).
Other platforms keep the existing kernels unchanged.
KexyBiscuit
pushed a commit
to tai-core/vllm-tracking
that referenced
this pull request
Nov 5, 2026
The grouped-GEMM permute (ep_scatter) launched one program per token and let every
thread of the block redo the same 8 scalar top-k lookups, so a layer paid ~375 us per
permute at 8k tokens while only ~30 us of that was actual row movement. ep_gather had
the same shape problem (one program per hidden chunk and token block, with a token
loop inside).
These kernels are the MUSA implementation of the permute/gather, selected through
current_platform.is_musa() like the other MUSA paths in this fork:
* route pairs with a 64-token tile so the top-k loads coalesce and the destination
atomics are issued as vectors;
* compute the per-expert start offsets on the device instead of with torch ops;
* copy the activation row together with its block scales in one kernel, driven by a
compact source-row map, so the scatter is a plain vectorised row copy;
* gather with one program per (token, hidden chunk) and a static top-k loop.
Measured on 8x MTT S5000, GLM-5.3-Flash, TP1 + PCP8 + EP8, 128 prompts x 8192 in:
permute 375 -> 120 us (3.1x), gather 128 -> 119 us (1.07x, bitwise identical)
end to end 16,744 -> 17,302 tok/s (+3.3%), median TTFT 30.99 -> 29.98 s
Correctness: every routed pair was compared against the stock kernel (activation
row, scales and m_indices all match) and greedy generation is token-identical to the
baseline (5/5 prompts, max |d mean logprob| = 5.35e-3).
Other platforms keep the existing kernels unchanged.
KexyBiscuit
pushed a commit
to tai-core/vllm-tracking
that referenced
this pull request
Nov 5, 2026
The grouped-GEMM permute (ep_scatter) launched one program per token and let every
thread of the block redo the same 8 scalar top-k lookups, so a layer paid ~375 us per
permute at 8k tokens while only ~30 us of that was actual row movement. ep_gather had
the same shape problem (one program per hidden chunk and token block, with a token
loop inside).
These kernels are the MUSA implementation of the permute/gather, selected through
current_platform.is_musa() like the other MUSA paths in this fork:
* route pairs with a 64-token tile so the top-k loads coalesce and the destination
atomics are issued as vectors;
* compute the per-expert start offsets on the device instead of with torch ops;
* copy the activation row together with its block scales in one kernel, driven by a
compact source-row map, so the scatter is a plain vectorised row copy;
* gather with one program per (token, hidden chunk) and a static top-k loop.
Measured on 8x MTT S5000, GLM-5.3-Flash, TP1 + PCP8 + EP8, 128 prompts x 8192 in:
permute 375 -> 120 us (3.1x), gather 128 -> 119 us (1.07x, bitwise identical)
end to end 16,744 -> 17,302 tok/s (+3.3%), median TTFT 30.99 -> 29.98 s
Correctness: every routed pair was compared against the stock kernel (activation
row, scales and m_indices all match) and greedy generation is token-identical to the
baseline (5/5 prompts, max |d mean logprob| = 5.35e-3).
Other platforms keep the existing kernels unchanged.
KexyBiscuit
pushed a commit
to tai-core/vllm-tracking
that referenced
this pull request
Nov 5, 2026
The grouped-GEMM permute (ep_scatter) launched one program per token and let every
thread of the block redo the same 8 scalar top-k lookups, so a layer paid ~375 us per
permute at 8k tokens while only ~30 us of that was actual row movement. ep_gather had
the same shape problem (one program per hidden chunk and token block, with a token
loop inside).
These kernels are the MUSA implementation of the permute/gather, selected through
current_platform.is_musa() like the other MUSA paths in this fork:
* route pairs with a 64-token tile so the top-k loads coalesce and the destination
atomics are issued as vectors;
* compute the per-expert start offsets on the device instead of with torch ops;
* copy the activation row together with its block scales in one kernel, driven by a
compact source-row map, so the scatter is a plain vectorised row copy;
* gather with one program per (token, hidden chunk) and a static top-k loop.
Measured on 8x MTT S5000, GLM-5.3-Flash, TP1 + PCP8 + EP8, 128 prompts x 8192 in:
permute 375 -> 120 us (3.1x), gather 128 -> 119 us (1.07x, bitwise identical)
end to end 16,744 -> 17,302 tok/s (+3.3%), median TTFT 30.99 -> 29.98 s
Correctness: every routed pair was compared against the stock kernel (activation
row, scales and m_indices all match) and greedy generation is token-identical to the
baseline (5/5 prompts, max |d mean logprob| = 5.35e-3).
Other platforms keep the existing kernels unchanged.
triangleXIV
pushed a commit
to tokmo-infra/vllm
that referenced
this pull request
Nov 9, 2026
…lm-project#17) The DSA indexer is not torch.compile'd, so the torch.ops.vllm.index_rope registration and the is_compiling branch are unused. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Speed before this PR:
Speed after this PR: