vllm.models.deepseek_v41.amd.ops.topk
¶
The sparse indexer's decode top-512 for gfx942 (topk512_gfx942.cu).
build builds the extension with hipcc into torch's extension cache (about
a minute), and later processes load the cached build. The mono decode layers
call it when the model is created, so that the build happens at startup and
not at the first decode step. The TP ranks share one build: torch's extension
loader makes the other ranks wait for the rank that builds it. When the build
fails, every hook here returns False and vLLM runs its own ops.
Functions:
-
build–Build or load the extension once, and return whether it is available.
-
candidate_logits_top_k–The hook in front of the dense logits of the decode indexer
-
candidate_top_k–The hook in front of the DSpark candidate mask of the decode indexer
-
decode_top_k–The hook in front of vLLM's decode top-k in the indexer's decode path
-
select_candidates–The hook in front of vLLM's select_candidate_blocks in the decode
-
skip_decode_fill–Whether the indexer's decode path (sparse_indexer.py) may skip vLLM's
-
top_k_per_row_decode_512–The contract of vLLM's ops.top_k_per_row_decode with topK = 512:
build()
¶
Build or load the extension once, and return whether it is available. A failed build, for example without hipcc or without a writable extension cache, logs a warning. The hooks then return False and vLLM runs its own top-k ops for the rest of the process.
Source code in vllm/models/deepseek_v41/amd/ops/topk.py
candidate_logits_top_k(q_fp8, kv_cache, weights, seq_lens, block_table, candidates, block_size, indices, topk_tokens, dense_is_aiter_gluon, requires_padding)
¶
The hook in front of the dense logits of the decode indexer (sparse_indexer.py), on layers 24 to 36.
When enabled() and the extension is built, a call that the hook
takes writes each row's top 512 among its candidate blocks to indices
and returns True. vLLM then skips its dense logits, its candidate mask and
its top-k for the layer. The call computes only the 2048 x 8 candidate
logits of each row (cand_logits.py), bit-identical to the dense kernel's,
and then runs the same top-512 as candidate_top_k. Otherwise this returns
False and vLLM runs the dense path.
The hook only takes calls whose dense logits would come from AITER's gfx942 Gluon kernel, because cand_logits.py reproduces that kernel's arithmetic. dense_is_aiter_gluon says whether they would.
Source code in vllm/models/deepseek_v41/amd/ops/topk.py
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | |
candidate_top_k(logits, next_n, seq_lens, candidates, block_size, indices, topk_tokens)
¶
The hook in front of the DSpark candidate mask of the decode indexer (sparse_indexer.py), on layers 24 to 36.
When enabled() and the extension is built, a call with topK 512
writes each row's top 512 among its candidate blocks to indices and
returns True. vLLM then skips its mask and its top-k. The mask writes -inf
to about 7 of every 8 logits of a 128k row, and the top-k then reads the
whole row. Here only the 2048 x 8 candidate logits of a row are read.
Otherwise this returns False and vLLM runs its mask and its top-k.
Source code in vllm/models/deepseek_v41/amd/ops/topk.py
decode_top_k(logits, next_n, seq_lens, indices, topk_tokens)
¶
The hook in front of vLLM's decode top-k in the indexer's decode path (sparse_indexer.py).
When enabled() and the extension is built, a call with topK 512 and
unit column strides runs here and returns True. Otherwise it returns
False and vLLM runs torch.ops._C.top_k_per_row_decode.
Source code in vllm/models/deepseek_v41/amd/ops/topk.py
select_candidates(logits, next_n, seq_lens, block_size, candidates)
¶
The hook in front of vLLM's select_candidate_blocks in the decode indexer (sparse_indexer.py), on layer 20, which writes the candidate blocks of layers 24 to 36.
When enabled() and the extension is built, candidates gets each
row's block ids from one launch (candidateBlocks in topk512_gfx942.cu) and
this returns True. vLLM takes three launches and torch.topk, which also
sorts the picks, and about 100 us for a 128k step's 6 rows. The block ids
are the same, in no particular order. Otherwise this returns False and
vLLM runs its version.
Source code in vllm/models/deepseek_v41/amd/ops/topk.py
skip_decode_fill(has_prefill, num_decode_tokens, num_tokens, decode)
¶
Whether the indexer's decode path (sparse_indexer.py) may skip vLLM's
-1 fill of the step's top-k rows. When enabled() and the extension is
built, it may when every row of the step is a decode row and none is
padded. The decode top-k then writes every entry of every row, the -1
past a short row's end included. The extension's top-k (decode_top_k and
candidate_top_k) and vLLM's top_k_per_row_decode both do. AITER's indexer
top-k, which runs before them on gfx950, is not used on gfx942. This saves
one launch on each of the 8 index layers.
Source code in vllm/models/deepseek_v41/amd/ops/topk.py
top_k_per_row_decode_512(logits, next_n, seq_lens, indices, max_blocks=MAX_BLOCKS, min_chunk=MIN_CHUNK, register_select=True)
¶
The contract of vLLM's ops.top_k_per_row_decode with topK = 512: indices[r, :512] gets the column indices of row r's 512 largest logits, in no particular order, and -1 past the row's length when it is shorter.
With register_select, rows of up to 1M logits that start at 16-byte
boundaries run selectFromRegisters, which keeps a block's logits in
registers. Other rows, and all rows without register_select, run the
gfx942 build of vLLM's topKPerRowJob. The index sets are the same, except
for ties at the cut.