veloxquant_mlx.quantizers.kitty module¶
Kitty quantizer — dynamic channel-wise mixed-precision key quantization.
Inspired by “Kitty: Plug-and-Play Continuous Batching with Dynamic Token Selection” (arXiv:2511.18643, Nov 2025, unreviewed preprint). Documented as “Kitty-adapted (VeloxQuant-MLX implementation)” — not a faithful port.
- Algorithm:
- For a given key tensor K ∈ R^{S×D}:
Compute per-channel sensitivity as the variance across the sequence dimension: σ²_j = Var(K[:, j]) for j in 0..D-1.
Rank channels by σ² descending. Top hi_fraction → hi_bit quantization. Remaining channels → lo_bit quantization.
Each channel group is independently quantized with asymmetric min/max group quantization (reusing _group_quant_dequant).
The full key tensor is reconstructed in fp16 for downstream SDPA.
Operating in the original key space (no projection) makes Kitty zero- calibration: no SVD, no codebook training, sensitivity computed on-the-fly from the incoming K tensor itself.
- Effective bit-width:
- avg_bits = hi_fraction × hi_bit + (1 − hi_fraction) × lo_bit
= 0.25 × 4 + 0.75 × 2 = 2.5 bits/element (default settings)
- Adaptation notes:
Paper uses static offline sensitivity ranking; we compute it online from each incoming key batch (prefill uses full batch variance; decode uses a running accumulator updated per token).
Values are left at fp16 — Kitty is a key-only method.
Static calibration path is NOT implemented (deferred; no calibration dataset requirement keeps the cache-only contract intact).
- veloxquant_mlx.quantizers.kitty.rank_channels_by_sensitivity(keys, hi_fraction=0.25)[source]¶
Rank key channels by variance; return hi/lo channel index splits.
- Parameters:
keys (
array) – Shape [S, D] fp16 or fp32. S is sequence length, D is head dim.hi_fraction (
float) – Fraction of channels routed to high-bit quantization.
- Return type:
- Returns:
(hi_indices, lo_indices) — sorted ascending lists of column indices. hi_indices: top hi_fraction channels by variance. lo_indices: remaining channels.
- veloxquant_mlx.quantizers.kitty.quantize_mixed_channels(keys, hi_indices, lo_indices, hi_bit=4, lo_bit=2, group_size=32)[source]¶
Apply mixed-precision quantization per channel group.
Hi channels (high variance) get hi_bit, lo channels get lo_bit. Quantization is asymmetric min/max grouped along the sequence axis.
- Parameters:
keys (
array) – [S, D] fp16 or fp32.hi_indices (
list[int]) – Column indices to quantize at hi_bit.lo_indices (
list[int]) – Column indices to quantize at lo_bit.hi_bit (
int) – Bit width for high-sensitivity channels.lo_bit (
int) – Bit width for low-sensitivity channels.group_size (
int) – Group size for quantization along axis 0.
- Return type:
array- Returns:
Reconstructed keys [S, D] fp16.
- veloxquant_mlx.quantizers.kitty.compute_running_variance(key_sum, key_sq_sum, n)[source]¶
Compute per-channel variance from running Welford-style accumulators.
- Parameters:
key_sum (
array) – [D] sum of all keys seen so far (fp32).key_sq_sum (
array) – [D] sum of squared keys seen so far (fp32).n (
int) – Number of tokens accumulated.
- Return type:
array- Returns:
Per-channel variance [D] fp32. Returns zeros if n < 2.
- veloxquant_mlx.quantizers.kitty.hi_mask_from_variance_batched(variance, hi_fraction)[source]¶
Batched-leading-axis channel ranking: variance
[N, D]-> hi-bit mask[N, D]bool.Replaces the per-row
.tolist()+ Pythonsorted()ranking inrank_channels_by_sensitivity()/ the decode branch ofKittyKVCache._quantize_keyswith one host-sync-freemx.argsortcall across allNrows (e.g. flattenedB*H) at once.mx.argsortbreaks ties the same way Python’s stablesorted()does (first index wins), so the selected channel set matches exactly.- Parameters:
variance (
array) –[N, D]fp32 per-row, per-channel variance.hi_fraction (
float) – Fraction of channels routed to high-bit quantization.
- Return type:
array- Returns:
[N, D]bool mask, True where the channel is in that row’s top-hi_fraction(by variance, descending; ties broken by lower channel index, matching Python’s stable sort).
- veloxquant_mlx.quantizers.kitty.quantize_mixed_channels_batched(keys, hi_mask, hi_bit=4, lo_bit=2, group_size=32)[source]¶
Batched-leading-axis equivalent of
quantize_mixed_channels().Quantizes the full
[N, S, D]tensor athi_bitand atlo_bitindependently (each a single batched group-quant call, see_group_quant_dequant_batched()), then selects per-row, per-channel between the two reconstructions withhi_mask— avoiding a ragged gather/scatter over per-row index lists of different composition. Verified bit-for-bit equivalent to loopingquantize_mixed_channels()over axis 0 with the correspondinghi_indices/lo_indices.- Parameters:
keys (
array) –[N, S, D]fp16 or fp32.hi_mask (
array) –[N, D]bool, True where that row’s channel is hi-bit (as returned byhi_mask_from_variance_batched()).hi_bit (
int) – Bit width for high-sensitivity channels.lo_bit (
int) – Bit width for low-sensitivity channels.group_size (
int) – Group size for quantization along the sequence axis.
- Return type:
array- Returns:
Reconstructed keys
[N, S, D]fp16.