feat: opt-in INT8 KV-cache quantization - #183
Open
drunkcoding wants to merge 11 commits into
Open
Conversation
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Contributor
Author
|
Momus plan review: [OKAY] on the first review round. |
added 9 commits
August 28, 2026 22:20
Add KVCacheFormat/KVCacheFormatName, resolve_kv_cache_format capability resolver, tokenwise symmetric INT8 quantizer with upward-rounded FP16 scales, and format-aware KVCacheSpec.page_size_bytes accounting.
Add LayeredPagedKVStore, LayeredKVPageChunk, allocate_layered_paged_kv_store with chunk writes, logical prefix reads, blocking page snapshot/restore, and layer/kernel/flashinfer views over a single layer-major payload.
Bind PagedAttentionBackend to a LayeredPagedKVStore for int8_sym, resolve the execution backend/format decision, quantize chunk writes, and route decode via native INT8 dispatch or FP32 dequantized SDPA. Extend paged_attention_fwd with key/value scale tensors and a probe_native_int8_binding capability check; pass layer_idx through Qwen3PagedAttention.
Add reusable paged_attention_int8.cuh/.cu implementing an INT8+FP16-scale paged-attention decode kernel with FP32 accumulation, register its wrapper in the single existing PYBIND11_MODULE, link the source via _PAGED_ATTN_SOURCES, and add a dedicated tests/cuda target plus Python MHA/GQA parity against an independent FP32 dequantized SDPA oracle.
Back PagedKVCache with a single LayeredPagedKVStore (legacy dimension constructor preserved), add a RESIDENT/SWAPPED residency state machine with swap_out(release_gpu_blocks=True), transactional swap-in, page-chunk truncation that slices INT8 scales, and free_gpu_blocks rejection of swapped sequences. Replace the scheduler two-call preemption with one ownership-transferring call, add ModelRunner store-identity validation, and add coordinator.set_kv_store.
Add ArcherConfig.kv_cache_format/kv_cache_allow_fallback (validated via KVCacheFormat.parse), descriptor-driven MemoryManager.get_max_kv_blocks format_name accounting (native unchanged, int8 counts FP16 scales), model_info_from_config MLA/GQA detection, and OpenAI server --kv-cache-format/--no-kv-cache-format-fallback flags wired into the engine config, with fail-closed native-binding capability tests.
Add deterministic tensor-level INT8-vs-native decode equivalence gates (fp16/bf16, MHA/GQA, page boundaries, zero and non-contiguous cases), a model-free 2048-step logit/token-agreement parity gate, exact INT8 storage byte/ratio assertions, and an env-gated WikiText-2 perplexity release gate.
Add a native vs int8_sym long-context A/B benchmark CLI with a BenchmarkResult schema that reports storage, transfer, and execution precision separately, a parent-directory-creating JSON writer, and a strict-fallback guard so a fallback cannot be reported as a quantized run.
Document the opt-in kv_cache_format contract: storage/transfer/execution precision table, exact memory formula, MHA/GQA scope with visible MLA and FlashInfer-bypass fallbacks, one-setting rollback commands, effective-format stats, and the long-context benchmark runbook. State that KIVI/KVQuant are motivation only and no universal 2-bit support is claimed.
Wire the opt-in format end-to-end: ContinuousBatchingEngine resolves the format decision from model config + capabilities, allocates the effective LayeredPagedKVStore, builds a store-backed PagedKVCache, sizes num_blocks per the effective format, and exposes requested/effective_kv_cache_format, execution backend, and decision reason via get_stats and /v1/config so a native fallback (e.g. MLA) is never reported as quantized.
Contributor
Author
|
Independent implementation verification:
PR remains draft for native CUDA and model-quality qualification. |
drunkcoding
marked this pull request as ready for review
September 2, 2026 21:53
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Implements the Momus-approved plan (
docs/superpowers/plans/2026-08-21-kv-cache-quantization.md) for an opt-in, correctness-gatedint8_sympaged KV-cache format behind a format abstraction, preserving existing attention execution dtypes and deterministic fallback to the native/SDPA paths.What landed
moe_infinity/runtime/kv_cache_format.py):KVCacheFormat,resolve_kv_cache_formatcapability resolver, tokenwise symmetric INT8 quantizer with upward-rounded FP16 scales (no-128, exact zero, element error<= stored_scale/2 + 1e-6),LayeredPagedKVStore/LayeredKVPageChunk, andmodel_info_from_configMLA/GQA detection.attention_backend.py,paged_attention_ops.py,qwen3_paged_attention.py): store-boundPagedAttentionBackendwithbind_store/write_chunk, INT8 decode via native CUDA dispatch or FP32 dequantized SDPA fallback,probe_native_int8_bindingcapability check,layer_idxthreading.extensions/kernel/paged_attention_int8.{cuh,cu},paged_attention.cu,setup.py): reusable INT8+FP16-scale paged decode kernel with FP32 accumulation, registered in the single existingPYBIND11_MODULE, linked via_PAGED_ATTN_SOURCES, plus a dedicatedtests/cudatarget. Verified MHA/GQA parity vs an independent FP32 dequantized SDPA oracle (max abs diff ~1e-4, cosine 1.0).kv_cache.py,model_runner.py,scheduler.py,kv_cache_offload_coordinator.py): single-ownerLayeredPagedKVStore, RESIDENT/SWAPPED residency state machine (swap_out(release_gpu_blocks=True), transactional swap-in, page-chunk truncation that slices INT8 scales,free_gpu_blocksrejects SWAPPED), single-call scheduler preemption, ModelRunner store-identity validation,coordinator.set_kv_store. Additive design preserves the legacy constructor and every existing test.config.py,memory_manager.py,api_server_v2.py,engine.py):kv_cache_format/kv_cache_allow_fallbackfields, descriptor-drivenget_max_kv_blocks(native unchanged, int8 counts FP16 scales),--kv-cache-format/--no-kv-cache-format-fallbackCLI, and end-to-end consumption inContinuousBatchingEngine— it resolves the decision from the model config + capabilities, allocates the effective-format store, builds a store-backedPagedKVCache, and exposesrequested/effective_kv_cache_format,kv_cache_execution_backend, andkv_cache_format_decision_reasonvia engine stats and/v1/config, so a native fallback (e.g. MLA) is never reported as quantized.benchmarks/serving/kv_cache_quantization.pyA/B matrix with separate storage/transfer/execution precision reporting and a strict-fallback guard; docs for the precision contract, memory formula, MLA/FlashInfer fallback, one-setting rollback, and effective-format stats.Precision & memory
int8_symstores INT8 payload + one FP16 scale per(layer, page, KV head, token); for the canonical(block_size=16, kv_heads=8, head_dim=128)page this is33,280bytes vs65,536native FP16 (0.5078125). Storage/transfer/execution precisions are reported separately so a fallback is never mistaken for a quantized run.Scope & fallback
MHA/GQA validated; MLA visibly falls back (
mla_not_validated) or errors under strict mode. FlashInfer stays active for native stores; anint8_symrequest bypasses FlashInfer (flashinfer_no_int8_sym_contract) into the built-in validated path. No universal low-bit or 2-bit claim is made; KIVI/KVQuant are motivation only.Verification
--kv-cache-format int8_symallocates an INT8 store and reportseffective_kv_cache_format=int8_sym; an MLA model reportseffective_kv_cache_format=native, reason=mla_not_validated.Environment blockers (recorded, not worked around)
compute-sanitizeris not installed in this environment, so the sanitizer memcheck steps could not be executed.tests/cudaCMake harness cannot configure here (its supported-Python gate is 3.8–3.11 vs installed 3.13, and cmake 3.28 + CUDA 13.1 fail Torch'senable_language(CUDA)toolkit-root detection). The kernel itself compiles vianvcc(JIT + setuptools); the added CMake target is syntactically valid.Type of Change
Checklist