Repository navigation
[None][perf] One-model speculative decoding: host work between steps, worker-produced target logits, KDA drafts' records #19989
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
Open
vsabavat
wants to merge
106
commits into
NVIDIA:main
Choose a base branch
from
vsabavat:k3-cons/b-runtime
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.
+3,527
−316
Open
Changes from all commits
Commits
Show all changes
106 commits
Select commit
Hold shift + click to select a range
1c1d49d
[None][perf] Cut host work between speculative decoding steps
vsabavat f6cb23b
[None][feat] KDA verify: optional per-token states in the V2 hybrid c…
vsabavat b44c537
[None][fix] spec_step_copies: store zeros past a row's accepted tokens
vsabavat 92d67f3
[None][test] spec_step_copies tests: side stream waits for the curren…
vsabavat f3cf23f
[None][fix] KV cache manager V2: keep the SSM pool at its live floor …
vsabavat 67d93e9
[None][fix] multi_stream_utils: record the calling stream on fn1's ou…
vsabavat 5e16d82
[None][fix] MNNVL all-reduce: keep a grown workspace's predecessor al…
vsabavat f0ff9a8
MNNVL all-reduce: run the workspace-growth graph test in the GB200 mu…
vsabavat 551ca16
[None][chore] MNNVL all-reduce test: yapf the workspace-growth test
vsabavat df9d9bf
[None][test] MNNVL all-reduce: one-rank test of the workspace's captu…
vsabavat fd1bddc
MNNVL all-reduce: count Lamport arrivals per CTA in the RMSNorm-fused…
vsabavat 7a7ccf3
MNNVL all-reduce: start every CTA of the cluster before the RMSNorm c…
vsabavat f467211
[None][fix] Kimi K3 attn_res_fwd online kernel: order the ws_stats re…
vsabavat 26cb3c3
[None][fix] Kimi K3 attn_res: cross-proxy fence before a consumer rel…
vsabavat 05e9e4f
[None][test] Kimi K3 attn_res: check the cross-proxy fence before eac…
vsabavat 1e0dceb
DFlash: start the dummy slot at context length 0 every step
vsabavat adb6618
[https://nvbugs/6852473][fix] Skip zero-row launches in fp4_quantize,…
vsabavat 5e23844
[None][fix] kda_prefill: return a new output tensor on every call
vsabavat 936f38f
[None][fix] Kimi Linear / Kimi K3: make fla-core a runtime dependency
vsabavat 0102a35
[None][fix] MNNVL all-reduce: keep a replaced workspace only if a cap…
vsabavat ba20fa1
[None][fix] DSpark GQA drafter: keep the checkpoint's trained mask-to…
vsabavat e30477f
[None][fix] KV cache manager V2: take the per-token KDA states out of…
vsabavat ea84b23
[None][perf] Mamba state metadata: skip unchanged per-step uploads
vsabavat 546e567
[None][perf] DFlash: skip unchanged slot-buffer copies on decode steps
vsabavat a9938c2
[None][fix] KV cache manager V2: count the live-floor KDA token-state…
vsabavat 54b87a2
[None][fix] KV cache manager V2: refuse per-token KDA states off the …
vsabavat 1e6eb67
[None][fix] KV cache manager V2: keep a suspended request's KDA repla…
vsabavat 10fd5cf
[None][fix] KV cache manager V2: refuse a KV pool rebalance with the …
vsabavat 50ac9d6
[None][fix] kda_prefill: release evicted scratch with its cache entry
vsabavat a0509b3
[None][fix] LoRA overlap: leave the output record to maybe_execute_in…
vsabavat 77a450e
[None][doc] multi_stream_utils: note the compiled path and the error'…
vsabavat c3ced8d
[None][test] test_multi_stream_utils: bound the capture's block count
vsabavat f39f875
[None][perf] Kimi K3 attn_res_fwd online kernel: double-buffer ws_sta…
vsabavat b2a6af4
Kimi K3 KDA prefill: K1 warps finish reading sPartialLast before the …
vsabavat 2e598e1
[None][feat] One-model speculative decoding: the worker produces the …
vsabavat b12bfad
DFlash: empty the dummy slot in the drafting step, not in prepare()
vsabavat ce1ae63
[None][feat] KDA: commit pending accepted drafts into the live pools
vsabavat f9d32b4
[None][fix] KV cache manager V2: commit a suspended request's KDA rep…
vsabavat 93c0b28
MNNVL all-reduce: remove LamportFlags' unused cluster-arrival mode
vsabavat 0c9ab14
Merge main 70193ec43b into k3-up/u1-engine-host-gap
vsabavat eda9db2
[None][fix] DSpark GQA drafter: check the kept mask row at load and c…
vsabavat a0fa306
[None][fix] Mamba2 metadata: upload CPU-tensor state indices through …
vsabavat fd37763
[None][test] copy_to_device_if_changed: check skipped copies in debug…
vsabavat bea6002
[None][perf] spec_step_copies: run on the SM 100 family (SM 100, 103,…
vsabavat 0e29964
[None][perf] spec_step_copies: drop the staged host-to-device copies,…
vsabavat 0cbb559
[None][fix] DSpark GQA drafter: keep no mask row for DFlash's default…
vsabavat b83f960
[None][fix] DSpark GQA drafter: keep the trained row of the worker's …
vsabavat c95eac1
[None][fix] KDA suspend: read the drafts' records as [slots, 3, num_s…
vsabavat dc903ae
[None][fix] KDA verify: size kda_state_tok for the drafts' records
vsabavat c05a0c3
[None][fix] KDA verify: drop the replay caches the drafts' records re…
vsabavat 44a06db
Merge main a1f562a696 into k3-up/u1-engine-host-gap
vsabavat 003f8d0
[None][fix] KDA suspend: commit and relocate without the replay caches
vsabavat de2f7e1
[None][fix] KV cache manager V2: count every live-floor SSM slot in t…
vsabavat 547f6bf
Merge #19831 (P1) at c3ced8d8c1 into the main fixes branch
vsabavat 70bb2a3
Merge #19828 (P2) at 0102a35eea into the main fixes branch
vsabavat 0778b55
Merge #19836 (P3) at 93c0b28bbd into the main fixes branch
vsabavat adce84a
Merge #19829 (P4) at f39f875fa8 into the main fixes branch
vsabavat cb4a371
Merge #19826 (P5) at b2a6af4680 into the main fixes branch
vsabavat 2cc72d5
Merge #19827 (P7) at b12bfad22c into the main fixes branch
vsabavat 21462e1
Merge #19840 (P8) at adb66182fa into the main fixes branch
vsabavat ddff9e8
Merge #19835 (P9) at 5e238440d7 into the main fixes branch
vsabavat ca4918f
Merge #19837 (P10) at 936f38fbe7 into the main fixes branch
vsabavat 67a3ad5
Merge #19842 (P11) at b83f960a1d into the main fixes branch
vsabavat 989766a
Merge #19846 (P12a) at f9d32b4c4d into the main fixes branch
vsabavat 347d22f
Merge #19854 (P13) at 50ac9d64e4 into the main fixes branch
vsabavat dc76338
Merge #19816 (U1) at 44a06db574 into the runtime branch
vsabavat 8002879
Merge #19814 (U3) at 2e598e10cb into the runtime branch
vsabavat a0712cb
Merge #19846 (P12) at 003f8d088d into the runtime branch: its two com…
vsabavat fa41a16
Merge #19817 (U2) at de2f7e12ef into the runtime branch
vsabavat 0d83ef5
Runtime branch: the blank line ruff-format wants between two merged t…
vsabavat 35433fb
[None][fix] thop_attention catalog test: do not probe a context lengt…
vsabavat eedff8c
Merge k3-cons/a-main-fixes (thop_attention test fix) into k3-cons/b-r…
vsabavat bcef591
Merge main f891b3d9ba into k3-cons/a-main-fixes
vsabavat 338f9d0
Merge k3-cons/a-main-fixes (main f891b3d9ba) into k3-cons/b-runtime
vsabavat c53ffc8
Merge main 3beeef3a5f into k3-cons/b-runtime
vsabavat bdadd40
[None][test] List the MNNVL capture-guard test in l0_dgx_b200.yml
vsabavat 305118f
Merge k3-cons/a-main-fixes (l0_dgx_b200 move) into k3-cons/b-runtime
vsabavat cd21be6
[None][fix] Enable the spec step-copy kernels on SM 100 only
vsabavat 3a990dc
Merge main 24d0f2716f into k3-cons/b-runtime
vsabavat 4552c8d
[None][feat] DSpark: load speculators-format drafter checkpoints
vsabavat c6cd921
Merge main (01a3a967a9) into k3-cons/a-main-fixes
vsabavat c44c900
Merge k3-cons/a-main-fixes (speculators DSpark loader, main 01a3a967a…
vsabavat 0fd5a3a
[None][fix] Ragged spec sampler tests: give the stub sampler B's stor…
vsabavat d639ec5
Merge main fcc4432bef into k3-cons/b-runtime
vsabavat 145def6
Merge main 16df7eaf25 into k3-cons/a-main-fixes
vsabavat 0ed2dfd
Merge k3-cons/a-main-fixes (main 16df7eaf25) into k3-cons/b-runtime
vsabavat 6a95a9e
[None][fix] KV cache manager V2: do not commit an unseeded disagg gen…
vsabavat 6b07622
Merge k3-cons/a-main-fixes (unseeded disagg KDA replay suspend fix) i…
vsabavat 63aa7a2
[None][chore] KV cache manager V2: separate KDA draft-record accounti…
vsabavat a486e00
Merge main fced9ff984 into k3-cons/a-main-fixes
vsabavat 52a3283
Merge k3-cons/a-main-fixes latest-main compatibility into k3-cons/b-r…
vsabavat cdbba03
test: isolate MNNVL workspace lifecycle from CUDA capture state
vsabavat 0202519
test: align hybrid fixtures and CUDA requirements with main
vsabavat 40df45e
Merge commit 'cdbba03f749f6012d8288d71c915c7af7f863ea6' into mr11/b
vsabavat 72bb8ca
test: remove obsolete MNNVL workspace dictionary assertion
vsabavat 951048b
Merge commit '72bb8ca0b8ad4f5086f6fe4e1162afc6de533f61' into mr11/b
vsabavat a1fb5ba
Merge upstream after A #19988 while preserving B runtime records
vsabavat 9afa851
Merge current upstream main for K3 B CI
vsabavat 1f94ed5
Own cached host-to-device copies and share metadata buffer snapshots
vsabavat 597e23a
Reject malformed DSpark auxiliary layer IDs before translation
vsabavat 3261a6f
Address speculative runtime review nits
vsabavat 6b3d878
[None][fix] Align Kimi cache test fixture with upstream mapping fields
vsabavat 28d1e2a
[None][chore] Merge current main after the Kimi fixture correction
vsabavat 413ee68
[None][chore] Merge current main dac84b01a6 into the K3 runtime branch
vsabavat 14a76b0
[None][fix] Refresh serving configuration schemas (By Agent)
VALLIS-NERIA cb9aa92
[None][chore] Merge current main c226e2d77c into the K3 runtime branch
vsabavat 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
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,45 @@ | ||
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| import os | ||
|
|
||
| import torch | ||
|
|
||
| _verify_skipped_device_copies = os.environ.get("TLLM_DEBUG_MODE", "")[0:1] == "1" | ||
|
|
||
|
|
||
| class DeviceCopyBuffer: | ||
| def __init__(self, tensor: torch.Tensor, *, pin_memory: bool = False): | ||
| self._tensor = tensor | ||
| self._pin_memory = pin_memory | ||
| self._last_host_values = None | ||
|
|
||
| @property | ||
| def tensor(self) -> torch.Tensor: | ||
| return self._tensor | ||
|
|
||
| def update(self, host: torch.Tensor, *, force: bool = False) -> None: | ||
| flat = host.reshape(-1) | ||
| n = flat.numel() | ||
| last = self._last_host_values | ||
| if not force and last is not None and last.numel() >= n and torch.equal(last[:n], flat): | ||
| if _verify_skipped_device_copies: | ||
| if self._tensor.is_cuda: | ||
| if torch.cuda.is_current_stream_capturing(): | ||
| return | ||
| torch.cuda.synchronize(self._tensor.device) | ||
| held = self._tensor.view(-1)[:n].cpu() | ||
| assert torch.equal(held, flat.to(held.dtype)), ( | ||
| f"DeviceCopyBuffer skipped a copy, but the buffer holds {held.tolist()} " | ||
| f"instead of {flat.tolist()}: something else wrote it" | ||
| ) | ||
| return | ||
| staging = torch.empty_like(flat, device="cpu", pin_memory=self._pin_memory) | ||
| staging.copy_(flat) | ||
| self._tensor.view(-1)[:n].copy_(staging, non_blocking=True) | ||
| if last is None or last.numel() <= n: | ||
| self._last_host_values = flat.clone() | ||
| else: | ||
| last = last.clone() | ||
| last[:n] = flat | ||
| self._last_host_values = last |
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
18 changes: 18 additions & 0 deletions
18
tensorrt_llm/_torch/cute_dsl_kernels/spec_step_copies/__init__.py
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,18 @@ | ||
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
| """The one-model speculative decoding step's eager copy passes as one CuTe DSL kernel each. | ||
|
|
||
| Import :mod:`.op` for the host side; nothing is imported eagerly here so that the CuTe DSL dependency stays optional. | ||
| """ |
283 changes: 283 additions & 0 deletions
283
tensorrt_llm/_torch/cute_dsl_kernels/spec_step_copies/op.py
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,283 @@ | ||
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
| """Host side of the one-model speculative decoding step's copy kernels (``spec_step_copies_kernel``). | ||
|
|
||
| ``SlotScatter`` moves a step's per-row outputs into the sampler's slot stores (one launch for the sampler's four | ||
| ``index_copy_``). ``StepInputGather`` performs the overlap scheduler's gathers from those stores into a decode step's | ||
| inputs (one launch for the engine's four). Each kernel takes every size and address as a launch argument, so it is | ||
| compiled once per process, on the first launch, which must happen outside CUDA-graph capture. The kernels are called | ||
| through TVM-FFI: a launch costs a few microseconds of host time. | ||
|
|
||
| Callers use them only where ``is_supported()`` holds. A call whose arguments are outside what the kernel covers launches | ||
| nothing and returns False; the caller then does that work itself. | ||
| """ | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| from typing import Any, ClassVar | ||
|
|
||
| import torch | ||
|
|
||
| from ...._utils import get_sm_version | ||
| from ...cute_dsl_utils import IS_CUTLASS_DSL_AVAILABLE | ||
|
|
||
|
|
||
| def is_supported() -> bool: | ||
| """Whether the kernels run on the current device: SM 100 (B200 / GB200) with the CuTe DSL installed. | ||
|
|
||
| The kernels are plain SIMT code (thread and block indices, global loads and stores), with nothing specific to an | ||
| architecture, but they are validated on SM 100 only; SM 103 and SM 107 keep the torch path. | ||
| """ | ||
| return IS_CUTLASS_DSL_AVAILABLE and torch.cuda.is_available() and get_sm_version() == 100 | ||
|
|
||
|
|
||
| def _is_i32(t: torch.Tensor) -> bool: | ||
| """A contiguous CUDA int32 tensor.""" | ||
| return t.is_cuda and t.dtype == torch.int32 and t.is_contiguous() | ||
|
|
||
|
|
||
| def _compile(name: str, args: tuple): | ||
| """Compile kernel ``name`` for its scalar ``args`` with TVM-FFI; a call then takes ``args`` and the CUDA stream | ||
| handle to launch on.""" | ||
| if torch.cuda.is_current_stream_capturing(): | ||
| raise RuntimeError( | ||
| f"spec_step_copies: the {name} kernel must run once outside CUDA-graph capture first " | ||
| "(it compiles on its first launch)." | ||
| ) | ||
| import cutlass.cute as cute | ||
|
|
||
| from . import spec_step_copies_kernel as kernel | ||
|
|
||
| return cute.compile( | ||
| getattr(kernel, name), *args, cute.runtime.make_fake_stream(), options="--enable-tvm-ffi" | ||
| ) | ||
|
|
||
|
|
||
| def _gather_shapes_ok( | ||
| store_next_new_tokens: torch.Tensor, | ||
| store_next_draft: torch.Tensor, | ||
| store_lens: torch.Tensor, | ||
| rows: int, | ||
| tokens_per_row: int, | ||
| draft_width: int, | ||
| ) -> bool: | ||
| """The overlap gather's stores are [width, slots, 1], [slots, draft width] and [slots], wide enough for a row.""" | ||
| num_slots = store_lens.numel() | ||
| return ( | ||
| store_lens.dim() == 1 | ||
| and store_next_new_tokens.dim() == 3 | ||
| and store_next_new_tokens.shape[1:] == (num_slots, 1) | ||
| and store_next_draft.dim() == 2 | ||
| and store_next_draft.shape[0] == num_slots | ||
| and 0 < tokens_per_row <= store_next_new_tokens.shape[0] | ||
| and 0 <= draft_width < tokens_per_row | ||
| and draft_width <= store_next_draft.shape[1] | ||
| and rows >= 0 | ||
| ) | ||
|
|
||
|
|
||
| class SlotScatter: | ||
| """The speculative sampler's store update as one kernel. | ||
|
|
||
| ``store[..., slots[r]] = outputs[row_begin + r]`` for every row ``r``, each row padded with zeros or cut to its | ||
| store's width. A row's ``new_tokens`` at or past its ``new_tokens_lens`` are stored as zeros: the forward writes | ||
| only column 0 of a context row, and readers of the store stop at that length. | ||
| """ | ||
|
|
||
| _kernel: ClassVar[Any] = None | ||
|
|
||
| def scatter( | ||
| self, | ||
| outputs: dict[str, torch.Tensor], | ||
| row_begin: int, | ||
| rows: int, | ||
| slots: torch.Tensor, | ||
| store_new_tokens: torch.Tensor, | ||
| store_next_new_tokens: torch.Tensor, | ||
| store_lens: torch.Tensor, | ||
| store_next_draft: torch.Tensor, | ||
| ) -> bool: | ||
| """Launch the store update on the current stream. | ||
|
|
||
| Args: | ||
| outputs: The forward's ``new_tokens`` [rows_total, a], ``next_new_tokens`` [rows_total, b], | ||
| ``new_tokens_lens`` [rows_total] and ``next_draft_tokens`` [rows_total, c], int32. | ||
| row_begin: The first row of ``outputs`` to move. | ||
| rows: The number of rows to move. | ||
| slots: The distinct slot of each moved row, int32 [>= rows] on the device. | ||
| store_new_tokens: int32 [width, num_slots, 1]. | ||
| store_next_new_tokens: int32 [width, num_slots, 1]. | ||
| store_lens: int32 [num_slots]. | ||
| store_next_draft: int32 [num_slots, width]. | ||
|
|
||
| Returns: | ||
| False, launching nothing, when an argument is outside what the kernel covers (a non-contiguous or | ||
| non-int32 tensor, a store of another layout, fewer output rows or slots than ``rows``); True otherwise. | ||
| """ | ||
| if rows == 0: | ||
| return True | ||
| new_tokens = outputs["new_tokens"] | ||
| next_new_tokens = outputs["next_new_tokens"] | ||
| lens = outputs["new_tokens_lens"] | ||
| next_draft = outputs["next_draft_tokens"] | ||
| num_slots = store_lens.numel() | ||
| tensors = ( | ||
| new_tokens, | ||
| next_new_tokens, | ||
| lens, | ||
| next_draft, | ||
| slots, | ||
| store_new_tokens, | ||
| store_next_new_tokens, | ||
| store_lens, | ||
| store_next_draft, | ||
| ) | ||
| if not ( | ||
| all(_is_i32(t) for t in tensors) | ||
| and new_tokens.dim() == next_new_tokens.dim() == next_draft.dim() == 2 | ||
| and lens.dim() == store_lens.dim() == 1 | ||
| and min(t.shape[0] for t in (new_tokens, next_new_tokens, lens, next_draft)) | ||
| >= row_begin + rows | ||
| and row_begin >= 0 | ||
| and slots.numel() >= rows | ||
| and store_new_tokens.dim() == store_next_new_tokens.dim() == 3 | ||
| and store_new_tokens.shape[1:] == (num_slots, 1) | ||
| and store_next_new_tokens.shape[1:] == (num_slots, 1) | ||
| and store_next_draft.dim() == 2 | ||
| and store_next_draft.shape[0] == num_slots | ||
| ): | ||
| return False | ||
| columns = max( | ||
| store_new_tokens.shape[0], store_next_new_tokens.shape[0], store_next_draft.shape[1], 1 | ||
| ) | ||
| args = ( | ||
| new_tokens.data_ptr(), | ||
| next_new_tokens.data_ptr(), | ||
| lens.data_ptr(), | ||
| next_draft.data_ptr(), | ||
| slots.data_ptr(), | ||
| store_new_tokens.data_ptr(), | ||
| store_next_new_tokens.data_ptr(), | ||
| store_lens.data_ptr(), | ||
| store_next_draft.data_ptr(), | ||
| rows, | ||
| row_begin, | ||
| columns, | ||
| num_slots, | ||
| store_new_tokens.shape[0], | ||
| new_tokens.shape[1], | ||
| store_next_new_tokens.shape[0], | ||
| next_new_tokens.shape[1], | ||
| store_next_draft.shape[1], | ||
| next_draft.shape[1], | ||
| ) | ||
| if SlotScatter._kernel is None: | ||
| SlotScatter._kernel = _compile("scatter", args) | ||
| SlotScatter._kernel(*args, torch.cuda.current_stream().cuda_stream) | ||
| return True | ||
|
|
||
|
|
||
| class StepInputGather: | ||
| """The overlap scheduler's gathers of a decode step's inputs from the sampler's slot stores, as one kernel.""" | ||
|
|
||
| _kernel: ClassVar[Any] = None | ||
|
|
||
| def gather( | ||
| self, | ||
| store_next_new_tokens: torch.Tensor, | ||
| store_next_draft: torch.Tensor, | ||
| store_lens: torch.Tensor, | ||
| slots: torch.Tensor, | ||
| pos_indices: torch.Tensor, | ||
| rows: int, | ||
| tokens_per_row: int, | ||
| draft_width: int, | ||
| input_ids: torch.Tensor, | ||
| input_begin: int, | ||
| draft_tokens: torch.Tensor, | ||
| draft_begin: int, | ||
| pos_offsets: torch.Tensor, | ||
| pos_begin: int, | ||
| kv_offsets: torch.Tensor, | ||
| kv_begin: int, | ||
| ) -> bool: | ||
| """Launch the gathers of the rows whose request ran in the previous step on the current stream. | ||
|
|
||
| For ``r < rows`` with ``s = slots[r]`` and ``j < tokens_per_row``: | ||
| ``input_ids[input_begin + r * tokens_per_row + j] = store_next_new_tokens[j, s, 0]``, | ||
| ``pos_offsets[pos_begin + r * tokens_per_row + j] = store_lens[pos_indices[r * tokens_per_row + j]]``, | ||
| ``draft_tokens[draft_begin + r * draft_width + j] = store_next_draft[s, j]`` for ``j < draft_width`` and | ||
| ``kv_offsets[kv_begin + r] = store_lens[s] - tokens_per_row``. Every tensor is int32 on the device; the | ||
| stores are [width, slots, 1], [slots, width] and [slots]. | ||
|
|
||
| Returns: | ||
| False, launching nothing, when an argument is outside what the kernel covers; True otherwise. | ||
| """ | ||
| tensors = ( | ||
| store_next_new_tokens, | ||
| store_next_draft, | ||
| store_lens, | ||
| slots, | ||
| pos_indices, | ||
| input_ids, | ||
| draft_tokens, | ||
| pos_offsets, | ||
| kv_offsets, | ||
| ) | ||
| if not ( | ||
| all(_is_i32(t) for t in tensors) | ||
| and _gather_shapes_ok( | ||
| store_next_new_tokens, | ||
| store_next_draft, | ||
| store_lens, | ||
| rows, | ||
| tokens_per_row, | ||
| draft_width, | ||
| ) | ||
| and slots.numel() >= rows | ||
| and pos_indices.numel() >= rows * tokens_per_row | ||
| and input_ids.numel() >= input_begin + rows * tokens_per_row | ||
| and draft_tokens.numel() >= draft_begin + rows * draft_width | ||
| and pos_offsets.numel() >= pos_begin + rows * tokens_per_row | ||
| and kv_offsets.numel() >= kv_begin + rows | ||
| and min(input_begin, draft_begin, pos_begin, kv_begin) >= 0 | ||
| ): | ||
| return False | ||
| if rows == 0: | ||
| return True | ||
| args = ( | ||
| store_next_new_tokens.data_ptr(), | ||
| store_next_draft.data_ptr(), | ||
| store_lens.data_ptr(), | ||
| slots.data_ptr(), | ||
| pos_indices.data_ptr(), | ||
| input_ids.data_ptr(), | ||
| draft_tokens.data_ptr(), | ||
| pos_offsets.data_ptr(), | ||
| kv_offsets.data_ptr(), | ||
| rows, | ||
| tokens_per_row, | ||
| draft_width, | ||
| store_lens.numel(), | ||
| store_next_draft.shape[1], | ||
| input_begin, | ||
| draft_begin, | ||
| pos_begin, | ||
| kv_begin, | ||
| ) | ||
| if StepInputGather._kernel is None: | ||
| StepInputGather._kernel = _compile("gather", args) | ||
| StepInputGather._kernel(*args, torch.cuda.current_stream().cuda_stream) | ||
| return True | ||
Oops, something went wrong.
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.