vllm.models.kimi_k3.nvidia.specialized_decode.drafter.attention
¶
Dense MLA decode of the DSpark draft block with the query tokens folded into heads.
A DSpark draft step runs k query tokens per request (anchor + k - 1 noise
tokens) through each dense MLA draft layer. The block is non-causal: every query
token of a request attends to exactly the same keys (the whole context plus the
block itself, already written to the cache). The stock FLASHINFER_MLA decode
has no non-causal flag, so it flattens the block into R * k independent
single-token rows, each with its own copy of the request's block table. Every row
then streams the request's whole latent cache again: k times the KV bytes, and
each CTA's MMA sees only the H local heads of one token (8 at TP8).
Absorbed MLA decode is MQA (one latent KV head), so query heads are independent
rows over a shared key set. Folding the k tokens of a request into the head
axis, [R * k, H, D] -> [R, 1, k * H, D], gives one decode row per request with
k * H heads over the same keys. That is the same attention, exactly: every
(token, head) pair still gets its own full softmax over the identical key set, at
the same precision (FP8 Q and KV, the stock bmm scales); only the kernel's tiling
(which CTA holds which head, the KV split) can differ. The KV is read once per
request instead of k times, and the MMA M grows k-fold (32-56 heads at TP8,
256-448 at TP1 / DCP).
The output [R, 1, k * H, L] and LSE [R, k * H] are the stock
[R * k, H, L] / [R * k, H] in the same memory order (token-major,
then head), so the DCP combine and the W_UV up-projection are unchanged.
Classes:
-
DraftDcp–The draft block's MLA decode under DCP (DCP = TP: rank d owns head block d)
Functions:
-
balanced_decode–The cute-dsl LSE decode of
common(folded_decode's FlashInfer -
balanced_tiers–The split tiers (rows each, longest first) of a cute-dsl LSE draft decode of
-
cake_supported–CAKE's Kimi K3 MLA kernel: SM100 family, FP8 query and cache, page 64,
-
cake_workspace_bytes–The largest CAKE split-KV workspace any folded draft batch of up to
-
draft_forward_mqa–FlashInferMLAImpl.forward_mqafor a DSpark draft block, folded. -
fold_plan–(query tokens folded into one decode row, FlashInfer MLA backend).
-
foldable–Query tokens per request when the decode batch can be folded, else 0.
-
folded_decode–Non-causal dense MLA decode of
Rrequests xkquery tokens. -
reserve_cake_workspace–Allocate the CAKE workspace for the deployment's largest draft batch now,
-
tier_workspace_bytes–The cute-dsl decode's split-KV workspace: FP32 partials + LSE per split
DraftDcp
¶
The draft block's MLA decode under DCP (DCP = TP: rank d owns head block d) on the specialized decode's DCP mailboxes, in three launches per layer instead of six (the direct-DCP epoch + query all-gather, the folded decode's split-KV + reducer, the LSE all-to-all push + combine) plus the W_UV bmm:
query every rank multicasts its FP8 query rows [T, H, 576] into head
block rank of every rank's DcpBox q mailbox [T, DCPH, 576]
(comm.Gather, in place) and polls until all landed
decode the stock folded draft decode (folded_decode: the k tokens of a
request folded into heads, every DCPH head over the local KV
shard, rank-local BF16 rows + LSE), reading the mailbox
value mla.dcp.DcpValue: re-arms the q mailbox, pushes each row to its
head owner, the owner merges its H heads over the DCP sources
(exp2(lse - max) / sum in FP32, one BF16 rounding, as the stock
combine) and applies W_UV (BF16 MMA, FP32 accumulation) into the
attention output. The draft layers have no output gate: the gate
operand is +inf (sigmoid exactly 1).
Same attention as the stock DCP decode at every stage: the decode kernel and its query are the stock ones; only the transport and the merge order differ.
Methods:
-
eligible–The draft layers this path serves: the stock folded draft decode
-
forward–attn(positions, hidden)(a draft layer's MultiHeadLatentAttention) on -
latent_major–W_UV [H, 512, 128] latent-contiguous, as DcpValue's MMA fragments load it
-
prepare–Each layer's latent-contiguous W_UV (1 MiB per draft layer), at load.
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/attention.py
654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 | |
eligible(attn, heads)
staticmethod
¶
The draft layers this path serves: the stock folded draft decode
(draft_fold on FlashInfer MLA, which takes the FP8 query this path
gathers), FP8 per-tensor KV, the q-LoRA path without output gate or fused
GEMM-RS-AR, H local heads of 576 / 512.
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/attention.py
forward(attn, positions, hidden, parity)
¶
attn(positions, hidden) (a draft layer's MultiHeadLatentAttention) on
this path, or None when this batch takes the stock module.
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/attention.py
latent_major(w_uv)
staticmethod
¶
W_UV [H, 512, 128] latent-contiguous, as DcpValue's MMA fragments load it (16 B along the latent); the module's is a transposed view.
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/attention.py
prepare(attentions)
¶
Each layer's latent-contiguous W_UV (1 MiB per draft layer), at load.
_balanced_tables(cache, bt, sl, tot, split_rows, pairs)
¶
Which rows the split tiers take, cached per batch like _group_tables
(every draft layer of a step sees the same lengths): of the split_rows
longest (longest first), those longer than MOVE of a pair's share of the
batch's keys (sum / pairs). Returns (each tier row's batch row, or
rows when it stays in the unsplit launch; every row's length in the
unsplit launch, 0 for the moved ones; the tier rows' block table, lengths
(0 when not moved) and global lengths).
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/attention.py
_compile_value(heads, size, batch, cap, w_uv, device, sms, q)
¶
mla.dcp.compile_value's BF16 DcpValue of batch rows (q per
request) for flashinfer's natural-log LSE (lse_scale log2(e)).
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/attention.py
_counter_buffer(max_reqs, num_heads, device)
¶
trtllm-gen's multi-CTA-KV semaphores (it resets them after each launch, so they are zeroed once). Sized for the deployment's largest batch and kept apart from the stock decode's buffer, so neither ever reallocates the other's under a captured CUDA graph.
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/attention.py
_group_tables(cache, block_table, seq_lens, tot, num_reqs, groups)
¶
Per decode-row tables when each request spans groups rows (cached per
batch: every draft layer of a step sees the same tables).
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/attention.py
_plan_kernel()
cached
¶
One CTA: which rows the split tiers take (see _balanced_tables).
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/attention.py
_row_copy(src, dst, target, bound, gather)
¶
See _row_copy_kernel; src / dst: [rows, ...] contiguous rows.
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/attention.py
_row_copy_kernel()
cached
¶
dst[i] = src[i] row by row (int32 words), for the rows whose target
is below bound only: gathers (gather: dst row i <- src row target[i])
or scatters (dst row target[i] <- src row i). Cost: the moved rows.
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/attention.py
_scales(impl, layer)
¶
The stock decode's bmm1 / bmm2 scales (FlashInferMLAImpl.forward_mqa).
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/attention.py
_streams(device, count)
¶
count streams, the first the highest priority, each next one lower.
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/attention.py
balanced_decode(common, table_cache, kv_lora_rank, tiers)
¶
The cute-dsl LSE decode of common (folded_decode's FlashInfer
arguments) as the split tiers of the longest rows and one unsplit launch
of the rest (see TIERS). Returns [rows, 1, heads, kv_lora_rank] BF16
and [rows, heads] FP32, as the one launch.
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/attention.py
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 | |
balanced_tiers(device, rows)
¶
The split tiers (rows each, longest first) of a cute-dsl LSE draft decode of
rows decode rows; () runs the one launch. Balanced from the row count on
which the one launch runs unsplit (sms // (2 * rows) < 2: below it the
kernel splits every row already), keeping at least half the rows unsplit.
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/attention.py
cake_supported(q, kv_cache, kv_lora_rank, rope)
¶
CAKE's Kimi K3 MLA kernel: SM100 family, FP8 query and cache, page 64, kv_lora_rank 512 / rope 64.
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/attention.py
cake_workspace_bytes(max_reqs, k, heads, max_seq_len, sm_count)
¶
The largest CAKE split-KV workspace any folded draft batch of up to
max_reqs requests needs (CUDA graphs plan at max_seq_len).
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/attention.py
draft_forward_mqa(impl, q, kv_cache, attn_metadata, layer)
¶
FlashInferMLAImpl.forward_mqa for a DSpark draft block, folded.
Returns None (the caller runs the stock forward_mqa) for a batch that
cannot be folded or a backend other than FLASHINFER_MLA.
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/attention.py
fold_plan(k, heads, need_lse, cake_ok)
¶
(query tokens folded into one decode row, FlashInfer MLA backend).
Without an LSE (TP / DEP) all k tokens fold into one row per request and
run the Kimi K3 CAKE kernel, whose two-CTA wide route shares each 128-key tile
across 128 packed (token, head) rows (auto = trtllm-gen when CAKE cannot
run: it reads the tile once per 64-head group). With an LSE (DCP) the cute-dsl
kernel takes at most 128 heads per row: fold the largest divisor f of
k with f * heads <= 128 (k=4 at 64 heads: pairs, half the KV reads).
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/attention.py
foldable(attn_metadata, num_rows)
¶
Query tokens per request when the decode batch can be folded, else 0.
Folding needs a non-causal decode batch in which every request has the same number of query tokens (a DSpark draft block always does).
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/attention.py
folded_decode(q, kv_cache, block_table, seq_lens, max_seq_len, tokens_per_request, *, kv_lora_rank, qk_nope_head_dim, qk_rope_head_dim, bmm1_scale, bmm2_scale, workspace, return_lse=False, dcp_world_size=1, dcp_rank=0, dcp_tot_seq_lens=None, max_reqs=0, backend=None, table_cache=None)
¶
Non-causal dense MLA decode of R requests x k query tokens.
q: [R * k, H, kv_lora_rank + rope] (token-major per request);
kv_cache: [pages, page_size, kv_lora_rank + rope]; block_table /
seq_lens (/ dcp_tot_seq_lens): per request. Returns [R * k, H,
kv_lora_rank] and, with return_lse, [R * k, H]. backend forces
a FlashInfer backend (benchmarks); by default :func:fold_plan picks.
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/attention.py
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 | |
reserve_cake_workspace(device, max_reqs, k, heads, max_seq_len)
¶
Allocate the CAKE workspace for the deployment's largest draft batch now,
at model load (before the KV-cache memory profile and every graph capture,
which bind its address), at most CAKE_WORKSPACE_MAX_BYTES. Returns its
size. (GB300, 1M plan length: TP8 64 x k5 6 MiB; DEP 128 x k4 324 MiB,
128 x k5 589 MiB, 256 x k5 4.9 GiB -> capped, its largest batches fold on
trtllm-gen.) An eager batch planned at a shorter length can need more; the
call then takes the same trtllm-gen fold. Without FlashInfer's CAKE planner
(capability fallback) nothing is reserved and the default buffer is used.
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/attention.py
tier_workspace_bytes(rows, splits, heads, lora)
¶
The cute-dsl decode's split-KV workspace: FP32 partials + LSE per split
(mla_decode.get_workspace_size).