ProprietaryLegal's picture
PLI Labs public snapshot 2026-10-28 (history squashed)
e1acc15
Raw History Blame Contribute Delete
12.7 kB
"""Small ops of the DSpark drafter forward, written to the engine's semantics (NOTES.md).
Everything here is plain torch except `markov_bias_rows`, a copy of the serve's Triton kernel
(vllm/models/deepseek_v41/nvidia/ops/markov_cache.py, Apache-2.0) so cached and computed Markov rows have the same
bits as on the Spark's code path. Float formats follow the engine: the hyper-connection stream and every activation
handed between modules are bf16; norms, mixes, RoPE, attention scores and routing are computed in fp32.
"""
from __future__ import annotations
import math
import torch
import triton
import triton.language as tl
# --------------------------------------------------------------------------------------------- RoPE
def rope_cos_sin(max_pos: int, rope_dim: int = 64, base: float = 10000.0, beta_fast: int = 32, beta_slow: int = 1,
orig_max_pos: int = 1048576) -> torch.Tensor:
"""fp32 [max_pos, rope_dim] = cat(cos, sin) exactly as vLLM's DeepseekV4ScalingRotaryEmbedding builds it for the
pure sliding-window layers (common/rope.py: rope_type deepseek_yarn, factor 1.0, mscale 1, original max position =
max_position_embeddings): the YaRN blend of two equal frequency sets, then an fp32 outer product with the
positions and cos / sin of each row. Built on the CPU like vLLM's (at module init, before .to(device))."""
pos_freqs = base ** (torch.arange(0, rope_dim, 2, dtype=torch.float) / rope_dim)
inv_freq_extrapolation = 1.0 / pos_freqs
inv_freq_interpolation = 1.0 / (1.0 * pos_freqs)
def corr_dim(num_rot: float) -> float:
return (rope_dim * math.log(orig_max_pos / (num_rot * 2 * math.pi))) / (2 * math.log(base))
low = max(math.floor(corr_dim(beta_fast)), 0)
high = min(math.ceil(corr_dim(beta_slow)), rope_dim - 1)
if low == high:
high += 0.001
ramp = torch.clamp((torch.arange(rope_dim // 2, dtype=torch.float) - low) / (high - low), 0, 1)
mask = 1 - ramp
inv_freq = inv_freq_interpolation * (1 - mask) + inv_freq_extrapolation * mask
t = torch.arange(max_pos, dtype=torch.float32)
freqs = torch.einsum("i,j -> ij", t, inv_freq)
return torch.cat((freqs.cos() * 1.0, freqs.sin() * 1.0), dim=-1)
def apply_rope(x: torch.Tensor, pos: torch.Tensor, cos_sin: torch.Tensor, inverse: bool = False) -> torch.Tensor:
"""Rotate the last rope_dim channels of x (interleaved pairs, as is_neox_style=False), in fp32, at positions pos.
x: [N, ..., D] (any float dtype), pos: [N] int64. Returns a new tensor in x's dtype; the NoPE channels are copied."""
rd = cos_sin.shape[-1]
cs = cos_sin[pos] # [N, rd]
cos, sin = cs[:, : rd // 2], cs[:, rd // 2:]
shape = [x.shape[0]] + [1] * (x.dim() - 2) + [rd // 2]
cos, sin = cos.view(shape), sin.view(shape)
if inverse:
sin = -sin
r = x[..., -rd:].float().unflatten(-1, (rd // 2, 2))
x0, x1 = r[..., 0], r[..., 1]
y = torch.stack((x0 * cos - x1 * sin, x1 * cos + x0 * sin), dim=-1).flatten(-2)
out = x.clone()
out[..., -rd:] = y.to(x.dtype)
return out
# --------------------------------------------------------------------------------------------- KV record
def kv_record_qdq(kv: torch.Tensor, nope: int = 448, group: int = 64) -> torch.Tensor:
"""Values of the V4 fp8_ds_mla record (SM12x, 584 B): the NoPE channels as e4m3 with one power-of-two (UE8M0) scale
per `group` channels, scale = 2^ceil(log2(amax / 448)); the RoPE channels kept bf16. Returns bf16 [.., 512] holding
exactly the values the engine's attention reads back (e4m3 x 2^k is exact in bf16).
The ceil(log2) is taken from the IEEE bits of amax * (1/448) (DeepSeek's fast_round_scale, the plugin's
_qdq_ue8m0 kernel): exact at powers of two, where log2f-then-ceil can round the wrong way."""
n = kv[..., :nope].float().unflatten(-1, (nope // group, group))
a = (n.abs().amax(-1, keepdim=True) * (1.0 / 448.0)).clamp_min(2.0 ** -126)
bits = a.view(torch.int32)
e = ((bits >> 23) & 0xFF) - 127 + ((bits & 0x7FFFFF) != 0).to(torch.int32)
scale = ((e + 127) << 23).view(torch.float32)
q = (n / scale).clamp(-448.0, 448.0).to(torch.float8_e4m3fn).float() * scale
out = kv.to(torch.bfloat16).clone()
out[..., :nope] = q.flatten(-2).to(torch.bfloat16)
return out
# --------------------------------------------------------------------------------------------- norms / mHC
def rms_norm(x: torch.Tensor, w: torch.Tensor, eps: float) -> torch.Tensor:
"""DeepSeek reference RMSNorm: fp32 math, weight applied in fp32, one rounding to x's dtype (bf16)."""
xf = x.float()
xf = xf * torch.rsqrt(xf.square().mean(-1, keepdim=True) + eps)
return (w.float() * xf).to(x.dtype)
def hc_mixes(stream: torch.Tensor, fn: torch.Tensor, scale: torch.Tensor, base: torch.Tensor, rms_eps: float,
hc_eps: float, iters: int) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
"""pre [T, hc], post [T, hc], comb [T, hc, hc] (fp32) from the bf16 stream [T, hc, H] (mhc_pre_delayed_torch)."""
hc = stream.shape[1]
x = stream.flatten(1).float()
mixes = (x @ fn.t()) * torch.rsqrt(x.square().mean(-1, keepdim=True) + rms_eps)
pre = torch.sigmoid(mixes[:, :hc] * scale[0] + base[:hc]) + hc_eps
post = torch.sigmoid(mixes[:, hc:2 * hc] * scale[1] + base[hc:2 * hc]) * 2.0
comb = mixes[:, 2 * hc:].view(-1, hc, hc) * scale[2] + base[2 * hc:].view(1, hc, hc)
comb = torch.softmax(comb, dim=-1) + hc_eps
comb = comb / (comb.sum(dim=-2, keepdim=True) + hc_eps)
for _ in range(iters - 1):
comb = comb / (comb.sum(dim=-1, keepdim=True) + hc_eps)
comb = comb / (comb.sum(dim=-2, keepdim=True) + hc_eps)
return pre, post, comb
def hc_collapse(stream: torch.Tensor, pre_mix: torch.Tensor | None) -> torch.Tensor:
"""[T, hc, H] -> [T, H]: copy 0 when pre_mix is None (the first stage), else sum_i pre_i * stream_i in fp32 -> bf16."""
if pre_mix is None:
return stream[:, 0].contiguous()
return (pre_mix.unsqueeze(-1) * stream.float()).sum(dim=1).to(stream.dtype)
def hc_post(y: torch.Tensor, stream: torch.Tensor, post: torch.Tensor, comb: torch.Tensor) -> torch.Tensor:
"""new stream_j = post_j * y + sum_i comb[i, j] * stream_i, fp32 -> bf16 (mhc_post_torch)."""
mixed = torch.einsum("tij,tih->tjh", comb, stream.float())
return (mixed + post.unsqueeze(-1) * y.float().unsqueeze(1)).to(stream.dtype)
# --------------------------------------------------------------------------------------------- routing
def route(x: torch.Tensor, gate_w: torch.Tensor, bias: torch.Tensor, top_k: int, route_scale: float
) -> tuple[torch.Tensor, torch.Tensor]:
"""sqrtsoftplus / noaux_tc: experts by top-k of score + bias, weights = the unbiased scores renormalized x scale.
gate_w fp32 [E, H]. Returns (ids int64 [T, k], weights fp32 [T, k])."""
logits = x.float() @ gate_w.t()
scores = torch.nn.functional.softplus(logits).sqrt()
ids = (scores + bias).topk(top_k, dim=-1)[1]
w = scores.gather(1, ids)
w = w / (w.sum(dim=-1, keepdim=True) + 1e-20) * route_scale
return ids, w
# --------------------------------------------------------------------------------------------- attention
def block_attention(q: torch.Tensor, ctx_kv: torch.Tensor, ctx_valid: torch.Tensor, blk_kv: torch.Tensor,
sink: torch.Tensor, scale: float) -> torch.Tensor:
"""The DSpark block attention: every block row sees the request's valid context window and the whole block.
q [B, k, Hh, D] bf16; ctx_kv [B, W, D] bf16 (keys = values, MQA); ctx_valid [B, W] bool; blk_kv [B, k, D] bf16;
sink [Hh] fp32 (joins the softmax denominator only). fp32 scores; the probabilities are rounded to bf16 for the
weighted sum (as DeepSeek's sparse_attn kernel and FlashInfer do), the denominator stays fp32; bf16 out."""
B, k, Hh, D = q.shape
keys = torch.cat((ctx_kv, blk_kv), dim=1).float() # [B, W + k, D] (exact bf16 values)
s = torch.bmm(q.reshape(B, k * Hh, D).float(), keys.transpose(1, 2)) * scale # [B, k*Hh, W+k]
valid = torch.cat((ctx_valid, torch.ones(B, k, dtype=torch.bool, device=q.device)), dim=1)
s = s.masked_fill(~valid.unsqueeze(1), float("-inf"))
sk = sink.view(1, 1, Hh).expand(B, k, Hh).reshape(B, k * Hh, 1)
m = torch.maximum(s.amax(-1, keepdim=True), sk)
p = torch.exp(s - m)
denom = p.sum(-1, keepdim=True) + torch.exp(sk - m)
o = torch.bmm(p.to(torch.bfloat16).float(), keys) / denom
return o.view(B, k, Hh, D).to(torch.bfloat16)
# --------------------------------------------------------------------------------------------- Markov bias
# Copied from vllm/models/deepseek_v41/nvidia/ops/markov_cache.py (the running image, Apache-2.0): one program per
# (row, 64 vocab columns); cached rows are read back, others computed as an fp32 dot over the rank, stored in the
# output dtype. The cache is filled by this same kernel, so a token's bias has the same bits either way.
_BLOCK_V = 64
@triton.jit
def _markov_bias_kernel(ids_ptr, slot_ptr, cache_ptr, emb_ptr, w2_ptr, out_ptr, V, cache_stride, w2_stride,
emb_stride, out_stride, R: tl.constexpr, BLOCK_V: tl.constexpr):
b = tl.program_id(0)
cols = tl.program_id(1) * BLOCK_V + tl.arange(0, BLOCK_V)
mask = cols < V
tok = tl.load(ids_ptr + b).to(tl.int64)
slot = tl.load(slot_ptr + tok)
if slot >= 0:
row = tl.load(cache_ptr + slot.to(tl.int64) * cache_stride + cols, mask=mask)
tl.store(out_ptr + b * out_stride + cols, row, mask=mask)
else:
r = tl.arange(0, R)
e = tl.load(emb_ptr + b * emb_stride + r).to(tl.float32)
w = tl.load(w2_ptr + cols[:, None].to(tl.int64) * w2_stride + r[None, :], mask=mask[:, None], other=0.0)
acc = tl.sum(w.to(tl.float32) * e[None, :], axis=1)
tl.store(out_ptr + b * out_stride + cols, acc.to(out_ptr.dtype.element_ty), mask=mask)
def markov_bias_rows(token_ids: torch.Tensor, slot_of_token: torch.Tensor, cache: torch.Tensor,
markov_embed: torch.Tensor, w2: torch.Tensor, out: torch.Tensor) -> torch.Tensor:
"""out[b] = cache[slot_of_token[t_b]] if cached, else w2 @ markov_embed[b] (fp32 dot, one rounding)."""
num_rows, rank = markov_embed.shape
vocab = w2.shape[0]
assert w2.stride(1) == 1 and markov_embed.stride(1) == 1 and out.stride(1) == 1
if num_rows == 0:
return out
grid = (num_rows, triton.cdiv(vocab, _BLOCK_V))
_markov_bias_kernel[grid](token_ids, slot_of_token, cache, markov_embed, w2, out, vocab,
cache.stride(0) if cache.numel() else 0, w2.stride(0), markov_embed.stride(0),
out.stride(0), R=rank, BLOCK_V=_BLOCK_V, num_warps=4)
return out
class MarkovBias:
"""The Markov bias with cached rows for the serve's most frequent tokens (VLLM_DSPARK_MARKOV_CACHE list, first
`rows` distinct ids, default 4096 like VLLM_DSPARK_MARKOV_CACHE_ROWS)."""
def __init__(self, w1: torch.Tensor, w2: torch.Tensor, token_list: list[int] | None, rows: int = 4096):
self.w1, self.w2 = w1, w2
vocab, dev = w1.shape[0], w2.device
ids: list[int] = []
seen: set[int] = set()
for t in token_list or []:
t = int(t)
if 0 <= t < vocab and t not in seen:
seen.add(t)
ids.append(t)
ids = ids[:rows]
self.slot_of_token = torch.full((vocab,), -1, dtype=torch.int32, device=dev)
self.cache = torch.empty((max(len(ids), 1), w2.shape[0]), dtype=torch.bfloat16, device=dev)
if ids:
tok = torch.tensor(ids, dtype=torch.int64, device=dev)
for s in range(0, len(ids), 256):
t = tok[s: s + 256]
markov_bias_rows(t, self.slot_of_token, self.cache, w1[t].contiguous(), w2, self.cache[s: s + 256])
self.slot_of_token[tok] = torch.arange(len(ids), dtype=torch.int32, device=dev)
self.cached_rows = len(ids)
def embed(self, token_ids: torch.Tensor) -> torch.Tensor:
return self.w1[token_ids]
def __call__(self, token_ids: torch.Tensor, markov_embed: torch.Tensor, out: torch.Tensor | None = None
) -> torch.Tensor:
if out is None:
out = torch.empty((markov_embed.shape[0], self.w2.shape[0]), dtype=torch.bfloat16,
device=markov_embed.device)
return markov_bias_rows(token_ids, self.slot_of_token, self.cache, markov_embed.contiguous(), self.w2, out)