vllm.models.kimi_k3.nvidia.specialized_decode.drafter.markov
¶
DSpark's sequential Markov sampling, one launch per draft step.
DSparkSpeculator._sample_sequential runs, for each of the k draft steps,
the Markov embedding of the previous token, the bias GEMV over the whole
vocabulary (markov_w2: 163840 x 256 BF16, 84 MB, replicated), the add to the
base logits ([R, 163840] written twice), the Gumbel sample (its kernel, a torch
argmax over the block maxima and a gather) and the copy into draft_tokens:
about nine launches and three full-vocabulary [R, V] tensors per step.
Here each step is two launches. The step kernel's programs each own 256
vocabulary entries and 16 request rows: they gather the rows' Markov embeddings
(markov_w1[prev]), stream their markov_w2 range in [64, rank] tiles and
multiply all rows at once on the tensor cores (FP32 accumulation), add the base
logits, write the step's logits into the draft logits cache and keep each row's
Gumbel-max over their range. A select launch (one program per row) takes the
first of the largest per-program maxima, which is the step's token: it writes
draft_tokens and the next step's previous token.
Exactness: the same sampling as vLLM's loop. The bias is the FP32 dot product of
the embedding and the markov_w2 row rounded once to the logits dtype (the GEMV
output dtype), the add is one FP32 add rounded to the logits dtype (a BF16 tensor
add), the cache holds the logits before temperature, and the Gumbel noise is
vLLM's own draw (murmur3 keyed by the request seed mixed with the draft step,
the position before the sampled token plus the draft salt, and the token id),
divided by the temperature exactly as gumbel_noised_argmax does. Only the
summation order of the 256-term bias dot product differs from cuBLAS's GEMV, as
any GEMM tiling may; ties keep the first token as vLLM's two-level argmax does.
Classes:
-
FusedMarkov–The fused Markov steps of one speculator (scratch sized for its largest
Functions:
-
sample_sequential–DSparkSpeculator._sample_sequentialwith the fused launches. Returns -
why_not–Why this draft step takes vLLM's loop, or None when the fused launches
FusedMarkov
¶
The fused Markov steps of one speculator (scratch sized for its largest batch, allocated once so captured graphs keep their addresses).
Methods:
-
fork_noise–Launch this draft step's Gumbel noise on a side stream (it depends only
-
noise_rows–Whether this batch's Gumbel noise is precomputed (FP32 noise, at most
-
run–base_logits: [num_reqs, k, V]; writes the draft logits cache and
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/markov.py
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 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 | |
fork_noise(spec, num_reqs, n_spec)
¶
Launch this draft step's Gumbel noise on a side stream (it depends only
on the seeds, the positions and the token ids, not on any logits), so it
runs beside the lm_head; join before the steps read it.
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/markov.py
noise_rows(num_reqs, n_spec)
¶
Whether this batch's Gumbel noise is precomputed (FP32 noise, at most
NOISE_ROWS sampled rows).
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/markov.py
run(spec, num_reqs, base_logits, w1, w2, noise=None)
¶
base_logits: [num_reqs, k, V]; writes the draft logits cache and
spec.draft_tokens[:num_reqs]. noise: fork_noise's (joined), or
None to hash the noise in the steps.
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/markov.py
_fused(spec, w1, w2, device)
¶
The speculator's FusedMarkov (markov_w2's vocabulary; sample_sequential
checks it against the base logits').
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/markov.py
_gumbel_key(lf, temp, seed, pos, v, USE_FP64)
¶
gumbel_noised_argmax's key of FP32 logits lf (temperature applied
in FP32, then the draft-salted noise; plain logits at temperature 0).
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/markov.py
_gumbel_log_arg32(seed, pos, v)
¶
The argument of the outer log of _gumbel_key's FP32 noise
-log(-log1p(-u)): the noise is -log of it. The step kernel takes that
last log itself, so its add to the logits compiles as in
gumbel_noised_argmax (a stored noise, added in another kernel, rounds
differently: 1 ulp on about a fifth of the keys).
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/markov.py
_loop_rest(spec, model, num_reqs, base_logits)
¶
The loop of vLLM from its base logits on (base logits computed once).
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/markov.py
sample_sequential(spec, model, num_reqs, head_hidden)
¶
DSparkSpeculator._sample_sequential with the fused launches. Returns
False, having done nothing, when this step takes vLLM's loop.
Source code in vllm/models/kimi_k3/nvidia/specialized_decode/drafter/markov.py
why_not(spec, model, num_reqs)
¶
Why this draft step takes vLLM's loop, or None when the fused launches compute the same sampling.