Skip to content

vllm.model_executor.models.qwen3_xpress

Classes:

XPressRefinerHead

Bases: Module

Methods:

  • build_fused_buffers –

    Transposed, contiguous weight views the fused kernels index directly.

Source code in vllm/model_executor/models/qwen3_xpress.py
class XPressRefinerHead(nn.Module):
    def __init__(
        self,
        vocab_size: int,
        hidden_size: int,
        block_size: int,
        rank: int = 256,
        mlp_hidden: int = 512,
        max_num_reqs: int = 256,
        topc: int = 512,
    ) -> None:
        super().__init__()
        self.vocab_size = int(vocab_size)
        self.hidden_size = int(hidden_size)
        self.block_size = int(block_size)
        self.rank = int(rank)
        self.max_num_reqs = int(max_num_reqs)
        # Score each pass on the base logits' top-C candidates instead of the full
        # vocabulary. The readout weight read per pass drops from [r, V] (78MB at
        # V=152k) to [r, C] gathered once per step, which is what the pass is
        # bandwidth-bound on. 0 keeps exact full-vocab scoring: under top-C the
        # refiner cannot reach a token the drafter left outside its top-C, so the
        # block it converges to is no longer the exact sequential decode.
        self.topc = int(topc)
        r = self.rank
        self.w1 = nn.Embedding(vocab_size, r)
        self.down_h = nn.Linear(hidden_size, r, bias=False)
        self.down_g = nn.Linear(hidden_size, r, bias=False)
        self.in_proj = nn.Linear(3 * r, r, bias=False)
        # Stored FOLDED (L*tril + I), so a refine pass is one bmm with no mask and no
        # residual add. Identity here means "no mixing" for a head built without
        # weights.
        self.mix_L = nn.Parameter(torch.eye(block_size).expand(r, -1, -1).contiguous())
        self.mlp_gate = nn.Linear(r, mlp_hidden, bias=False)
        self.mlp_up = nn.Linear(r, mlp_hidden, bias=False)
        self.mlp_down = nn.Linear(mlp_hidden, r, bias=False)
        self.w2 = nn.Linear(r, vocab_size, bias=False)
        self._scratch: dict | None = None
        self._fused_buf: dict | None = None

    def _scratch_buffers(self, dtype: torch.dtype, device: torch.device) -> dict:
        """Buffers for the fused Jacobi passes, allocated once at max_num_reqs.

        Not allocated in the constructor: the dtype and device a head ends up
        serving on are not known until it is called. The first call is the memory
        profiling run, so the footprint is still accounted for before the KV cache
        is sized.
        """
        if self._scratch is None:
            B = self.block_size
            rows = self.max_num_reqs * (B - 1)
            nvb = (self.vocab_size + 4095) // 4096
            self._scratch = {
                "lat": torch.empty(
                    self.max_num_reqs, B - 1, self.rank, dtype=dtype, device=device
                ),
                "bias": torch.empty(rows, self.vocab_size, dtype=dtype, device=device),
                "base": torch.empty(rows, self.vocab_size, dtype=dtype, device=device),
                "ov": torch.empty(rows, nvb, dtype=torch.float32, device=device),
                "oi": torch.empty(rows, nvb, dtype=torch.int64, device=device),
            }
        return self._scratch

    @torch.no_grad()
    def fold_from_raw_(self, raw_L: torch.Tensor) -> None:
        # Training stores the raw mixer and adds the sublayer residual: x + (L*tril)x.
        # Baking the mask and the identity into the parameter makes that one bmm, and
        # keeps a checkpoint meaning the same thing at serving time as it did in
        # training.
        B = self.block_size
        tril = torch.tril(torch.ones(B, B, dtype=raw_L.dtype, device=raw_L.device))
        eye = torch.eye(B, dtype=raw_L.dtype, device=raw_L.device)
        self.mix_L.copy_(raw_L * tril + eye)

    def hidden_cache(self, h_full: torch.Tensor) -> torch.Tensor:
        # Pass-invariant: only prev_ids changes between Jacobi passes, so compute the
        # hidden half once per block and reuse it for all K passes.
        g = h_full.mean(dim=1, keepdim=True).expand_as(h_full)
        return torch.cat([self.down_h(h_full), self.down_g(g)], dim=-1)

    def _refine_latent(
        self, prev_ids: torch.Tensor, hcache: torch.Tensor
    ) -> torch.Tensor:
        lat = self.w1(prev_ids)
        x = self.in_proj(torch.cat([hcache, lat], dim=-1))
        # Per-channel causal mix: position k sees only j <= k, which is what makes
        # Jacobi iteration valid -- a settled prefix cannot be disturbed by later slots.
        x = torch.bmm(self.mix_L.to(x.dtype), x.permute(2, 1, 0)).permute(2, 1, 0)
        return x + self.mlp_down(F.silu(self.mlp_gate(x)) * self.mlp_up(x))

    def refine_bias(self, prev_ids: torch.Tensor, hcache: torch.Tensor) -> torch.Tensor:
        return self.w2(self._refine_latent(prev_ids, hcache))

    def jacobi_refine_greedy(
        self,
        base_logits_full: torch.Tensor,
        h_full: torch.Tensor,
        anchor_ids: torch.Tensor,
        tok_am1_ids: torch.Tensor,
        num_passes: int,
    ) -> torch.Tensor:
        # Greedy, so a settled prefix stays settled and K passes converge monotonically.
        N, B, _ = base_logits_full.shape
        hcache = self.hidden_cache(h_full)
        blk = torch.empty(N, B, dtype=torch.long, device=h_full.device)
        blk[:, 0] = anchor_ids

        assert self.max_num_reqs >= N, (
            f"{N} requests exceeds the max_num_reqs={self.max_num_reqs} the "
            "scratch buffers were sized for"
        )
        buf = self._fused_buf
        assert buf is not None, (
            "the fused buffers are built from the loaded weights; call "
            "build_fused_buffers() first"
        )
        rows = N * (B - 1)
        v = base_logits_full.shape[-1]
        blk[:, 1:] = base_logits_full[:, 1:, :].argmax(dim=-1)

        if self.topc:
            # One pass over the base logits yields the candidate set, its logits and
            # the block's starting argmax: the chunk maxima's own maximum IS the
            # full-vocabulary argmax. Gathered once per draft step, never rescored
            # between passes, which is what keeps the per-pass [r, V] read away.
            c = min(self.topc, v)
            slots = base_logits_full[:, 1:, :]
            # _topk routes to flashinfer's kernel when it is available, which is
            # about twice torch.topk's speed and is the largest fixed cost of this
            # path. The candidate set is only ever indexed, never traversed in rank
            # order, so its ordering does not matter.
            base_c, cand = _topk(slots.reshape(rows, v), c)
            base_c, cand = base_c.view(rows, c), cand.view(rows, c)
            w2c = self.w2.weight[cand].reshape(rows, c, self.rank)
            xh0 = torch.mm(hcache.view(N * B, -1), buf["whc_t"]).view(N, B, self.rank)
            lat0 = torch.empty(
                N,
                B - 1,
                self.rank,
                dtype=base_logits_full.dtype,
                device=base_logits_full.device,
            )
            for _ in range(num_passes):
                kernels.xpress_latent_pass(
                    blk,
                    tok_am1_ids,
                    xh0,
                    lat0,
                    self.w1.weight,
                    buf["wlat_t"],
                    buf["mix_kjc"],
                    buf["wg_t"],
                    buf["wu_t"],
                    buf["wd_t"],
                )
                bias_c = torch.bmm(w2c, lat0.view(rows, self.rank, 1)).view(N, B - 1, c)
                # One launch for add + argmax + the candidate-to-vocab gather.
                kernels.fused_topc_argmax_to_blk(
                    base_c.view(N, B - 1, c), bias_c, cand.view(N, B - 1, c), blk
                )
            return blk[:, 1:]

        sc = self._scratch_buffers(base_logits_full.dtype, base_logits_full.device)
        lat, bias = sc["lat"][:N], sc["bias"][:rows]
        base, ov, oi = sc["base"][:rows], sc["ov"][:rows], sc["oi"][:rows]
        base.copy_(base_logits_full[:, 1:, :].reshape(rows, v))
        xh = torch.mm(hcache.view(N * B, -1), buf["whc_t"]).view(N, B, self.rank)
        # Three launches per pass: latent, the w2 GEMM, then add+argmax straight
        # into blk. The [N, B, V] sum is never materialized.
        for _ in range(num_passes):
            kernels.xpress_latent_pass(
                blk,
                tok_am1_ids,
                xh,
                lat,
                self.w1.weight,
                buf["wlat_t"],
                buf["mix_kjc"],
                buf["wg_t"],
                buf["wu_t"],
                buf["wd_t"],
            )
            torch.mm(lat.view(rows, self.rank), buf["w2_t"], out=bias)
            kernels.fused_add_argmax_to_blk(base, bias, ov, oi, blk)
        return blk[:, 1:]

    @torch.no_grad()
    def build_fused_buffers(self) -> None:
        """Transposed, contiguous weight views the fused kernels index directly.

        Called once weights are loaded, not in the constructor: mix_kjc is derived
        from mix_L, which only takes its serving form in fold_from_raw_().
        """
        r = self.rank
        w = self.in_proj.weight.detach()
        self._fused_buf = {
            "whc_t": w[:, : 2 * r].t().contiguous(),
            "wlat_t": w[:, 2 * r :].t().contiguous(),
            "mix_kjc": self.mix_L.detach().permute(1, 2, 0).contiguous(),
            "wg_t": self.mlp_gate.weight.detach().t().contiguous(),
            "wu_t": self.mlp_up.weight.detach().t().contiguous(),
            "wd_t": self.mlp_down.weight.detach().t().contiguous(),
            "w2_t": self.w2.weight.detach().t().contiguous(),
        }

    HYBRID_KEY_MAP = {
        "w1.weight": "w1.weight",
        "down_h.weight": "down_h.weight",
        "down_g.weight": "down_g.weight",
        "in_proj.weight": "in_proj.weight",
        "mix.L": "__raw_mix_L__",
        "mlp.gate_proj.weight": "mlp_gate.weight",
        "mlp.up_proj.weight": "mlp_up.weight",
        "mlp.down_proj.weight": "mlp_down.weight",
        "w2.weight": "w2.weight",
    }

_scratch_buffers(dtype, device)

Buffers for the fused Jacobi passes, allocated once at max_num_reqs.

Not allocated in the constructor: the dtype and device a head ends up serving on are not known until it is called. The first call is the memory profiling run, so the footprint is still accounted for before the KV cache is sized.

Source code in vllm/model_executor/models/qwen3_xpress.py
def _scratch_buffers(self, dtype: torch.dtype, device: torch.device) -> dict:
    """Buffers for the fused Jacobi passes, allocated once at max_num_reqs.

    Not allocated in the constructor: the dtype and device a head ends up
    serving on are not known until it is called. The first call is the memory
    profiling run, so the footprint is still accounted for before the KV cache
    is sized.
    """
    if self._scratch is None:
        B = self.block_size
        rows = self.max_num_reqs * (B - 1)
        nvb = (self.vocab_size + 4095) // 4096
        self._scratch = {
            "lat": torch.empty(
                self.max_num_reqs, B - 1, self.rank, dtype=dtype, device=device
            ),
            "bias": torch.empty(rows, self.vocab_size, dtype=dtype, device=device),
            "base": torch.empty(rows, self.vocab_size, dtype=dtype, device=device),
            "ov": torch.empty(rows, nvb, dtype=torch.float32, device=device),
            "oi": torch.empty(rows, nvb, dtype=torch.int64, device=device),
        }
    return self._scratch

build_fused_buffers()

Transposed, contiguous weight views the fused kernels index directly.

Called once weights are loaded, not in the constructor: mix_kjc is derived from mix_L, which only takes its serving form in fold_from_raw_().

Source code in vllm/model_executor/models/qwen3_xpress.py
@torch.no_grad()
def build_fused_buffers(self) -> None:
    """Transposed, contiguous weight views the fused kernels index directly.

    Called once weights are loaded, not in the constructor: mix_kjc is derived
    from mix_L, which only takes its serving form in fold_from_raw_().
    """
    r = self.rank
    w = self.in_proj.weight.detach()
    self._fused_buf = {
        "whc_t": w[:, : 2 * r].t().contiguous(),
        "wlat_t": w[:, 2 * r :].t().contiguous(),
        "mix_kjc": self.mix_L.detach().permute(1, 2, 0).contiguous(),
        "wg_t": self.mlp_gate.weight.detach().t().contiguous(),
        "wu_t": self.mlp_up.weight.detach().t().contiguous(),
        "wd_t": self.mlp_down.weight.detach().t().contiguous(),
        "w2_t": self.w2.weight.detach().t().contiguous(),
    }