vllm.models.deepseek_v41.amd.ops.cand_logits
¶
The indexer logits of the DSpark candidate positions on gfx942.
Layers 24 to 36 take their top 512 only from the 2048 candidate blocks of 8 positions that layer 20 chose for each decode row. vLLM computes such a layer's logits for every position of the row with AITER's deepgemm_fp8_paged_mqa_logits. Then topk942's gatherCandidates copies the 16384 candidate logits of each row into a compact row, and topK512Candidates takes the top 512 of that row. At 128k context the dense call scores 8 times more positions than the top-k reads.
_cand_logits_kernel computes only the candidate logits and writes the compact
row directly. Position i of row r holds the logit of column
8 * cand[r][i // 8] + i % 8 and that column as its id. It holds -inf and id
-1 when the block entry is -1 or the column is at or past the row's end.
This is what gatherCandidates writes.
Each logit is computed with the code of AITER's gfx942 kernel (_gluon_deepgemm_fp8_paged_mqa_logits_preshuffle in aiter/ops/triton/gluon/pa_mqa_logits.py). It uses the same MFMA layout. It multiplies the queries of all heads with the column's key starting from zero, multiplies by the key's scale, applies ReLU, multiplies by the head weights, and adds the heads up with the same reduction. The sum over the heads runs inside one wave, along the heads of one column, so its order does not depend on which position a column holds. Only the address of each column's key differs from the dense kernel. So every logit is bit-identical to the dense kernel's logit of that position (tests/kernels/models/amd/test_dsv41_gfx942_cand_logits.py).
Functions:
-
candidate_logits–Writes the compact candidate rows described in the module docstring.
-
split_cache–The FP8 keys and the FP32 key scales of an indexer cache of shape
candidate_logits(q_fp8, kv_cache, weights, seq_lens, next_n, block_table, candidates, cand_block, out_logits, out_ids, stages_per_program=0)
¶
Writes the compact candidate rows described in the module docstring. stages_per_program overrides STAGES_PER_PROGRAM when it is not 0.
q_fp8 is [rows, heads, dim] FP8, with row r the draft position r % next_n of request r // next_n. kv_cache is the paged indexer cache, weights [rows, heads] FP32, block_table one row of pages for each request, seq_lens the lengths as the dense call gets them, candidates [rows, blocks] int32 with -1 padding, and out_logits and out_ids contiguous [rows, blocks * cand_block].
Source code in vllm/models/deepseek_v41/amd/ops/cand_logits.py
split_cache(kv_cache)
¶
The FP8 keys and the FP32 key scales of an indexer cache of shape [pages, page size, 1, dim + 4], split the way AITER's deepgemm_fp8_paged_mqa_logits splits it: each page holds page size x dim FP8 values and then page size FP32 scales.