Pull requests / #242

#242 IQ kernels: decode each weight part once for every column and entry, bitwise identical

closed · @gputier · 0 comentários · No GitHub

BenchmarksSetup & installAMD / HIPNVIDIA / CUDAModels & quantsWindows

Descrição

## IQ kernels: decode each weight part once for every column and entry, bitwise identical

Rebased on v0.1.29. One commit: `iq_kernels.cu` and its header, a new parity test (`iq_multi_parity`), and additions to `iq_parity` and `native_expert_parity`.

### What it does

`iq_mmvq`, `native_gu_kernel` and `native_down_kernel` called the format's dot once per column (or group entry), re-reading the weight words and redoing the grid lookups and sign unpacking each time. Each dot is now split into a load (weight side) and an apply (activation side, same integer chain and same float expression), the way `native_mmvq.cu`'s multi-column traits already work. The dense kernel takes 1, 2, 4 or 8 columns per pass (8 at a time beyond 8), the grouped ones 4 entries per pass (about 48 registers; the default verify window fits in one pass).

Every column keeps the same calls, lane stride, summation order and `warp_sum`, so results are bitwise equal to the old kernels.

### Default path is identical to the byte

Measured on an RTX 5090 (sm_120, Windows, MSVC 2022, CUDA 13.4), Release build, v0.1.29 as the base.

- `iq_multi_parity` (new, in ctest, synthetic, no model): old against new bitwise for iq2_xxs, iq2_xs, iq3_xxs, iq4_nl, iq3_s, iq2_s, iq4_xs, iq1_m and q2_0, `iq_mmvq` with 1 to 8 and 11 columns, and `native_expert_grouped` with 9 groups and 35 entries for the 24 pairings of 8 gate/up formats with IQ4_NL, Q2_0 and IQ4_XS down. 0 failures.
- `native_expert_parity` on the real IQ3_S shard (layers 0, 1, 2, 3, 20, 47): 0 failures, and for each layer "gpu decode-once vs per-entry kernels: bitwise equal".
- `iq_parity` now also requires every column of a 1 to 8 column `native_mmvq` call to equal a one-column call bitwise. `tools/iq_fixture.py` is not in the tree, so I ran it on fixtures built locally from gguf-py (random valid blocks, 64 x 512, dequantized by gguf-py from the pinned llama.cpp): 8 IQ formats and Q3_K pass, dequant error 0, dot within 6e-3 of the float product, and the multi-column check holds. Q2_0 has no gguf-py fixture and reports "missing fixture", exactly as v0.1.29 does.
- Full ctest, same machine: v0.1.29 alone 35 of 38 pass, this branch 36 of 39. The same three fail in both, only because the Q2_0 model files are not installed: `ple_parity`, `expert_parity`, `pool_test`.
- End to end greedy A/B against v0.1.29 alone, IQ3_S model, `--spec 4 --expert-cache 8000 --prefill 2048 --max-new 256`, three prompts (32, 2 520 and 23 020 tokens), two passes each: all 256 output tokens are identical in every run, and identical with `STRATA_OLD_IQ_MMVQ=1` on the shortest and longest prompt.

### Gain

Kernel micro-benchmark (`iq_multi_parity --bench`, RTX 5090, idle GPU), microseconds per call, old / new:

| call | 1 column | 4 columns | 8 columns |
| --- | --- | --- | --- |
| IQ2_XXS `iq_mmvq` 8192 x 2560 | 10.0 / 9.9 | 18.5 / 13.3 | 29.9 / 20.5 |
| IQ3_S `iq_mmvq` 8192 x 2560 | 10.5 / 9.3 | 21.1 / 16.1 | 38.9 / 20.5 |
| IQ1_M `iq_mmvq` 8192 x 2560 | 10.2 / 9.9 | 20.5 / 15.1 | 34.8 / 20.5 |

Grouped, 16 groups of m entries (IQ3_S gate/up with Q2_0 down): m=1 39.9 / 40.1, m=4 76.0 / 54.1, m=8 129.4 / 90.2. Across the six formats benchmarked, m=8 goes from 109 to 129 us down to 82 to 90 us.

End to end, no gain shows on the IQ3_S model with the default `--spec 4` window: decode is 142.8 tok/s for v0.1.29 and 142.8 / 143.3 for this branch on the 23K prompt, and 137.5 / 136.9 against 138.8 / 138.1 on the 2.5K one, within run to run noise. Most of the win is at 3 or more columns or entries per call, which the default window rarely reaches on this model.

### Switch back

`STRATA_OLD_IQ_MMVQ=1` (or `iq_set_old_kernels`) keeps the per-column kernels.

### Not tested

- HIP / ROCm: not built, not run.
- Two GPUs or more.
- Quants other than IQ3_S end to end (the other formats are covered by the synthetic and fixture parity tests only), and a larger `--spec` window where the multi-column path is hit more often.
- Sampled (non-greedy) generation, and architectures other than sm_120.

No site

Links install, modelos, releases.