loopyt afbfdb6c7a feat(triton): port the sampler, bit-exact on the draw and honest about the rest
`fused_sample` for the configuration the engine builds: 4096 columns after the force_topk cut,
sampling on, rejection off. With one tile the baseline's two-level search collapses -- the coarse
offset *is* the token id -- so this implements log-softmax, the top-k/top-p cut as a threshold plus
the tie rule, renormalisation, a fixed-point cumulative distribution and one Philox draw.

The draw matches cuRAND bit for bit (that is what the previous commit established). The rest does
not all match, and the split is measured rather than claimed:

    engine's configuration (top_p=0.99, 2644 kept columns)   tokens identical on every row
    narrow cuts (top_k=128, top_p=0.5)                       ~90% of rows

Kept sets match column for column and log-probabilities agree to ~1e-5 in every case. What differs
is the token, and the cause is a discontinuity in the baseline rather than a defect here: the draw
is `d % total` with `total = sum(floor(p_i * 2^31))`, and the baseline's rejection limit
`(2^32-1) // total * total` steps from `2 * total` to `1 * total` exactly at `total == 2^31` -- which
`total` sits next to, because the probabilities sum to one. On the near side almost no draw is
rejected, on the far side about half are, and each rejection moves to the next draw. A few units of
rounding error in `total`, which is a reduction order that cannot match, therefore change the token
outright. Clamping `total` under 2^31 does not help: the baseline crosses in either direction too,
so it only relocates the disagreement (30 rows instead of 11).

Four bugs found on the way, all worth recording because each looked like something else:

- Triton evaluates `//`, `%` and `<=` on **uint32 operands with signed arithmetic**, so 4294967295
  behaves as -1. That made `limit` come out as `2^32 - total`, flipping the rejection decision.
  Fixed by doing the whole cumulative distribution in int64.
- Nested runtime `if`s produced a threshold that was not the one assigned inside the branch; the
  cuts are now combined with `tl.where` instead.
- The threshold was taken from the probability array and compared against logits. The sort has to be
  of the logits (equivalent, since the map is monotone -- the mass is recomputed from the sorted
  logits rather than sorting twice).
- Renormalising by division rather than through the log domain, as the baseline does, moved the
  token agreement from 76% to 91% before the remaining gap was understood.

Also gives the A/B harness a fourth case element: an agreement floor for outputs whose answer is a
random draw, so the rate is reported rather than compared for equality -- a comparison that can pass
without testing anything would be worse than none.
2026-10-22 08:55:10 +08:00
..
tilelang_ops feat(triton): port the sampler, bit-exact on the draw and honest about the rest 2026-10-22 08:55:10 +08:00
__init__.py initial commit 2026-10-20 12:09:42 +08:00
attention_backend.py initial commit 2026-10-20 12:09:42 +08:00
layernorm.py initial commit 2026-10-20 12:09:42 +08:00
linear.py feat: add SM90 (Hopper) support for DeepSeek-V4.1 inference 2026-10-21 15:18:56 +08:00
mtp_info_pool.py initial commit 2026-10-20 12:09:42 +08:00
rotary_embedding.py initial commit 2026-10-20 12:09:42 +08:00
sampler_utils.py initial commit 2026-10-20 12:09:42 +08:00
sampler.py fix(debug): move debug_dump out of h20_ops so other platforms can import it 2026-10-21 22:37:49 +08:00
vocab_parallel_embedding.py initial commit 2026-10-20 12:09:42 +08:00