Llama: support quantized KV cache export for Arm - #21574
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/21574
Note: Links to docs will display an error until the docs builds have been completed. ❌ 2 New Failures, 1 Unclassified FailureAs of commit 7b6c114 with merge base 27d4962 ( NEW FAILURES - The following jobs have failed:
UNCLASSIFIED FAILURE - DrCI could not classify the following job because the workflow did not run on the merge base. The failure may be pre-existing on trunk or introduced by this PR:
This comment was automatically generated by Dr. CI and updates every 15 minutes. |
139c00d to
5488666
Compare
5488666 to
80d3f12
Compare
|
Hi @digantdesai and @rascani this might need your review :) |
80d3f12 to
a0d8396
Compare
| use_kv_cache: bool = False | ||
| quantize_kv_cache: bool = False | ||
| static_quantize_kv_cache: bool = False | ||
| static_kv_cache_scale: float = 1.0 / 127.0 |
There was a problem hiding this comment.
Nit:
| static_kv_cache_scale: float = 1.0 / 127.0 | |
| static_quantize_kv_cache_scale: float = 1.0 / 127.0 |
There was a problem hiding this comment.
Updated to static_quantize_kv_cache_scale for consistency with static_quantize_kv_cache.
| cache[:, input_pos] = value | ||
|
|
||
| def _quantize_and_update(self, input_pos, k_val, v_val, indices=None): | ||
| quantized_k_val = self._quantize(k_val, self.k_cache_scales) |
There was a problem hiding this comment.
can we use torchao affine quant util functions here?
There was a problem hiding this comment.
I investigated torchao.quantize_affine. It exports as torch.ops.torchao.quantize_affine.default, which currently lacks the required ExecuTorch Arm/TOSA lowering and runtime support. I retained the decomposed implementation and documented the constraint.
digantdesai
left a comment
There was a problem hiding this comment.
Thanks. Wonder how well does this per channel quant performs for a random prompts to the LLM.. it would be good to include w/ and w/o static quant eval numbers.
digantdesai
left a comment
There was a problem hiding this comment.
Thanks. Good to share some w/ and w/o static quant eval for ramdom llm prompts.
|
LGTM, can't stamp it ATM, Github is having some issues.. |
2 similar comments
|
LGTM, can't stamp it ATM, Github is having some issues.. |
|
LGTM, can't stamp it ATM, Github is having some issues.. |
digantdesai
left a comment
There was a problem hiding this comment.
curious to know w/ and w/o static quant for a random LLM. Thanks.
|
@claude review this PR. |
|
Claude finished @digantdesai's task in 2m 19s —— View job PR Review: Llama quantized KV cache export for Arm
Overall this is a clean, well-tested addition. The Correctness1. if not torch.any(self.k_observed_max) or not torch.any(self.v_observed_max):
raise RuntimeError("Static KV cache calibration observed no K/V values")This fires only if every head-dim channel observed zero. If a single channel never sees a non-zero value, its scale becomes 2. self.k_cache_scales.copy_(k_scales.clamp_min(torch.finfo(k_scales.dtype).tiny))
3. Full-cache dequant every decode step — k_out = self._dequantize(self.k_cache, self.k_cache_scales, k_val.dtype)Each Design / maintainability4. Reuse torchao affine quant utils (echoing @digantdesai's inline comment at 5. max_batch_size, n_heads, max_context_length, head_dim = kv_cache.k_cache.shape
if isinstance(kv_cache, CustomKVCache):
max_batch_size, max_context_length, n_heads, head_dim = kv_cache.k_cache.shapeThe first unpack is immediately overwritten for 6. Validation is duplicated between Nits
Eval numbers@digantdesai asked several times (and it's the right ask): please include with/without static-quant eval numbers on a few random LLM prompts. Per-head-dim symmetric quant shared across heads (scales are None of the above are hard blockers on the mechanics — the plumbing and lowering look correct. Items 1, 4, and the eval numbers are the ones I'd prioritize. |
|
Try to address small things Claude finds. |
|
@digantdesai thanks for your review. We evaluated SmolLM2 linear16a8w using nine greedy prompts to check quality by eye and 50 Wikitext prompts with 3,150 scored tokens for perplexity calculation on FVP CS-320. The context length is 64. Static KVQ produced coherent generations and perplexity 45.53, compared with the plain-KV linear16a8w baseline around 45. Though the current implementation of static KV cache is a functional but not performant path, and more work needs to be done to get it performant. |
Add a calibrated static int8 KV cache mode with per-channel qparams learned before export. Use standard tensor cache updates for TOSA, VGF, and Ethos-U. Wire model configuration, export validation, cache replacement, calibration, and Arm lowering. Load the standard quantized AOT library for static KVQ exports when portable QDQ boundaries require per-tensor out variants. AI-assisted-by: Codex Signed-off-by: Xingguo Li <xingguo.li@arm.com> Change-Id: Ica8dcc059df3bbdc94b426ee972a8a09f5efbff0
a0d8396 to
7b6c114
Compare
|
@claude here are my replies, all implemented in the latest PR. Scale dtype Full-cache dequantization torchao affine utilities from_float() shape handling Duplicated validation Naming and string cleanup Evaluation |
|
Claude finished @xingguo01's task in 1m 0s —— View job Verification of addressed review itemsI re-read the latest revision on
On the remaining items
Everything I flagged has been addressed or reasonably deferred. No further changes requested from my side — this LGTM on the mechanics. (Note: I can't submit a formal GitHub approval; @digantdesai's approval stands.) |
Add a calibrated static int8 KV cache mode with per-channel qparams learned before export. Use standard tensor cache updates for TOSA, VGF, and Ethos-U. Wire model configuration and export validation, and cover cache replacement, calibration, and Arm lowering.
Load the standard quantized AOT library for static KVQ exports when portable QDQ boundaries require per-tensor out variants.
cc @digantdesai @freddan80 @per @zingo @oscarandersson8218 @mansnils @Sebastian-Larsson @robell @rascani