Skip to content

perf(cuda/kv): validate and enable quantized KV cache modes on CUDA #635

Description

@inureyes

Part of #623.

Context

Quantized KV cache modes exist and are wired through both CLI and server: KVCacheMode = Fp16 (default), Int8, Turbo4Asym (fp16 K + 4-bit V), Turbo4, Turbo3Asym, Turbo4Delegated (src/lib/mlxcel-core/src/cache.rs:153-186; group size default 64 in cache/batch_quant.rs; server config kv_cache_mode/batch_kv_quant at src/server/config.rs:556-557, applied in scheduler.rs:2007; env gates MLXCEL_TURBO4_* in docs/environment-variables.md:171-176).

These were developed and benchmarked on Metal (scripts/bench_m5_kv_int8.sh, M5-era docs). Their CUDA status is unverified: the Turbo paths involve custom SDPA/dequant kernels that may be Metal-only (same situation as paged attention, #634), and no CUDA benchmark exists.

Why it matters on GB10: decode is bandwidth-bound, and at long context the KV read stream rivals or exceeds the weight stream. An 8B model at 32k context reads ~4 GB of fp16 KV per token step (GQA-dependent); Int8/4-bit KV halves/quarters that, directly raising long-context decode tok/s. This is one of the few levers that improves single-stream decode beyond the weight-bandwidth roofline.

Scope

  1. Audit which KV quant modes function on CUDA today.
  2. Fix or port what is broken (Int8 first, Turbo second).
  3. Benchmark and document CUDA guidance.

Implementation plan

  1. Audit: grep the Turbo implementation (src/lib/mlxcel-core/src/cache/turbo/, cache.rs quant branches at :3702-3718 for rotating, :2499-2624 update/fetch) for metal_kernel or Metal-only assumptions. Run each mode on GB10 CLI (--kv-cache-mode int8, turbo variants; check the actual flag names in src/commands/generate.rs and server config) on llama-3.1-8b-4bit and record: works / wrong output / crash ("No Metal back-end" abort expected wherever a metal_kernel hides).
  2. Int8 path: expected to be plain MLX ops (quantize/dequantize/qmm); if functional, benchmark 8k/32k-context decode vs Fp16 (use perf(bench): long-prompt prefill benchmark coverage and serving TTFT/decode-rate telemetry #624 long-prompt harness with long generations) and measure quality drift (greedy divergence step count + a small perplexity spot check).
  3. Turbo paths: where a Metal kernel blocks them, either port via fast::cuda_kernel (pattern: src/lib/mlxcel-core/cpp/mlx_cxx_kernels.cpp) or explicitly gate them off on CUDA with a clear error instead of an abort. Coordinate with perf(cuda/attn): port the native paged-attention decode kernel to CUDA #634 (a quantized paged-attention CUDA kernel would subsume some of this; do not duplicate).
  4. Server integration check: batch_kv_quant applied at scheduler.rs:2007 must interact correctly with prompt-cache donation/adoption (quantized detached caches) and --max-kv-size trimming (the audit note at scheduler.rs:4310-4313 says Turbo modes skip trim; verify Int8 trim on CUDA).
  5. Document a CUDA recommendation in docs (e.g. "Int8 KV for >8k contexts on CUDA: +X% decode at 32k, quality delta Y").

Acceptance criteria

  • Status matrix (mode x works/output-quality/perf on CUDA) committed to a dated docs/benchmark_results/ note.
  • Int8 KV: functional on CUDA CLI and server, measured long-context table (2k/8k/32k) vs Fp16 committed; no crash paths remain for unsupported modes (clean error, not abort).
  • At 32k context on llama-3.1-8b-4bit, Int8 KV decode tok/s exceeds Fp16 KV by a measured margin (expected 15%+ from halved KV traffic; record actual).
  • Prompt-cache adopt/donate and max-kv-size trim work under Int8 on CUDA (integration test or scripted E2E).
  • cargo test --features cuda passes.

Validation

cargo build --release --features cuda
./target/release/mlxcel-bench-decode --model ./models/llama-3.1-8b-4bit --prompt-tokens 32768 --max-tokens 256                    # fp16 KV
./target/release/mlxcel-bench-decode --model ./models/llama-3.1-8b-4bit --prompt-tokens 32768 --max-tokens 256 --kv-cache-mode int8

References

  • Modes: src/lib/mlxcel-core/src/cache.rs:153-186; turbo dir src/lib/mlxcel-core/src/cache/turbo/; batch quant cache/batch_quant.rs.
  • Server plumbing: src/server/config.rs:556-557, src/server/batch/scheduler.rs:2007,4310-4313.
  • Metal-era benches: scripts/bench_m5_kv_int8.sh, scripts/bench_kv_cache.sh.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions