Skip to content

SnapKV-style prefill KV eviction (stacks on TurboQuant) #51

Description

@pekkah

Background

TurboQuant compresses each KV entry to 3–4 bits. SnapKV (arXiv:2404.14469) and successors (PyramidKV, Ada-KV) attack the orthogonal axis: they reduce the number of KV positions retained after prefill, by scoring each prompt token's importance via the attention it receives from the last ~64 query tokens, then dropping all but the top-K.

The two compose multiplicatively. With TurboQuant at 4-bit (4× over fp16) + SnapKV at 4× position pruning, total KV footprint drops ~16× vs fp16 baseline — meaningful for 12 GB cards at long context.

SnapKV is prefill-only: it runs once at the end of prefill, decides which positions to keep, and the decode path is unchanged afterward. No per-step overhead.

Scope

  1. Add a post-prefill hook in ForwardPass.Prefill / HybridForwardPass.Prefill / CudaHybridGdnForwardPass.Prefill that:
    • Computes attention scores from the last W query tokens (W=64) over all prompt tokens, per head.
    • Pools across heads (mean or sum), keeps top-K positions per layer.
    • For the K=last-N positions, always keep (recency window).
  2. Compact the PagedKvCache (and TurboQuantKvCache variant) to retain only the selected positions. Update position metadata so RoPE re-application during decode addresses the surviving positions correctly — or, simpler, mark dropped positions as zero-mask in the attention kernel.
  3. Add SHARPI_SNAPKV_BUDGET=2048 env (or CLI flag --kv-budget) controlling K. Default off.
  4. Optionally implement PyramidKV layer-varying budget on top: more budget for low layers, less for high layers, matching observed attention sparsity.

Acceptance

  • At K=2048 on a 16K-token prompt, KV memory drops ~8× with ≤ 2 % accuracy regression on a reasonable benchmark (LongBench subset or needle-in-haystack).
  • No measurable decode-throughput regression (prefill-only cost).
  • Composes cleanly with TurboQuant — both compressors active simultaneously.
  • Works on CUDA, Vulkan, and CPU backends.

Open questions

  • Position renumbering vs masking — masking is simpler but wastes KV-cache slots (we still allocate pages). For 12 GB this matters; compaction is the right answer.
  • Per-head budgets (Ada-KV) vs per-layer budgets (PyramidKV) vs uniform (SnapKV) — pick after measurement.

References

  • SnapKV: arXiv:2404.14469
  • PyramidKV: arXiv:2406.02069
  • Ada-KV: arXiv:2407.11550

Related

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions