
源碼精讀篇本文為源碼/方法論精讀無獨立實測文中數字均引述倉庫 docs 的板端實測記錄一句話導讀q8 KV把 K、V 從 f16 壓到 INT8按每 token 每頭定標量化逐字節算清緩存與 decode 掃描帶寬省約一半的賬并講清 KV 為何敢量化、f32 為何只是調試探針。8-3 我們把 KV 的布局講清楚了可一個殘酷的事實還在KV 是模型里除權重外最肥的東西。8K 上下文 × 28 層 × 8 KV 頭 × 128 維若用 f16 存 K、V 各一份光這一塊就約 560MB——decode 每詞還要把它們全掃一遍。今天把 KV 也量化成 q8看帶寬怎么壓到約一半。1. 知識點為什么 KV 敢量化權重能 Q4/Q8第 5 天KV 為什么不能量化 KV 的顧慮是“精度”但注意兩個事實decode 只“讀”KVK/V 一旦寫入就只被乘與累加量化誤差只影響當次注意力打分/加權不像權重誤差會一層層傳播疊加KV 每維都有獨立的 scale引擎對每個 (token, head) 單獨定標見下128 維共享一個 scale誤差被鎖在“一行的局部”不會累積。于是引擎默認把內存 KV 壓成INT8q8每個元素從 2 字節f16降到 1 字節K、V 各一份直接砍半再配合 8-3 的“decode 掃全 KV”路徑每詞的 KV 讀取帶寬同比例減半另有更狠的--kv-q4模式K/V 再壓一半約 1.65 倍更密Day 24 思路同源。2. 對應代碼q8 KV 的存儲與“一 token 一 scale”引擎在分配階段默認走 q8vllm_safetensors.c 第 8208–8244 行/* Compressed KV cache: INT8 (near-lossless) by default; --kv-q4 switches * to the Q4_0 payload cache (~1.65x denser, decode dot without dequant). */ st-use_kv_q8 g_kv_q4 ? 0 : 1; ... st-k_cache_q8[l] alloc_kv_blocks_i8(n_blocks, bs, kv_dim, ...); st-k_scale[l] cf_calloc_guard((size_t)max_seq * nkv, sizeof(float), ...); /* 每 token 每頭一個 scale */寫入時按“每 token 每頭”做 max-abs INT8 量化第 9466–9476 行if (st-use_kv_q8) { /* Per-token per-head max-abs INT8 K/V quantization (near-lossless). */ int8_t *kdst kv_row_i8(st-k_cache_q8[l], cl, kv_dim, st-kv_bs); int8_t *vdst kv_row_i8(st-v_cache_q8[l], cl, kv_dim, st-kv_bs); kv_quantize_per_head(kdst, vdst, st-k_scale[l] (size_t)cl * nkv, st-v_scale[l] (size_t)cl * nkv, st-k_buf, st-v_buf, nkv, hd); /* Also store in float cache */ /* fp32 鏡像仍保留調試/對照用 */ memcpy(... k_buf, kv_dim * sizeof(float)); ... }逐字節算筆賬2B 模型參數nkv8、hd128即每個 token 每層 K 與 V 各kv_dim 1024f16 KV K 1024×2B V 1024×2B 4096 B / token / 層 q8 KV K 1024×1B V 1024×1B 2048 B scale8 頭 × (K、V 各一) × 4B 64 B 合計 2112 B / token / 層 → 4096 → 2112緩存字節與 decode 全量掃描帶寬均 ×0.52省約 48%接近一半scale 的粒度是“每個 (token, 頭)”——比“整層一個 scale”細得多這正是 q8 KV 敢自稱 near-lossless 的原因9-3 會給實測誤差。3. 改動后果關掉 q8 KV 試試--kv-q4 / 全 f32 的代價引擎把 KV 模式做成可切默認 q8near-lossless解碼走 INT8 單遍9-2 主角--kv-q4切到 Q4_0 payload 緩存比 q8 再密 ~1.65 倍decode 點積免反量化直接吃 nibble全 f32 的 KV代碼注釋明確記為DEBUG 用途第 8210–8214 行曾用來排查 K 緩存損壞定位后恢復生產默認——f32 KV 不是給生產用的是調試探針。想親眼看到“KV 模式影響帶寬”連跑--bench-mixed之外的 decode 場景不現實無直接開關計時但可以換位驗證——8-3 說過 decode 每詞掃全 KVKV 從 4096B/token/層f16降到 2112Bq8后decode 的 KV 掃描帶寬需求直接 ×0.52這正是基準報告里 8K decode 引擎能維持 ~137ms/詞vs llama f16-KV 全掃 411ms的重要來源之一疊加 Day 10 的稀疏詳見 9-2/10 天。4. 學員調試任務A 檔板端動手跑引擎--kv-q4與默認模式各一次短生成同一 prompt記錄輸出 token 是否一致q4 KV 比 q8 更激進肉眼可看的場景值得留個心眼用 5-1 的解析腳本確認模型 KV 相關張量名結合本頁算一遍“2B 8K 上下文 q8 KV 約多少 MB”8K×28 層×2112B≈?。B 檔純讀源碼讀alloc_kv_blocks_i8/kv_quantize_per_head在 vllm_safetensors.c 內搜索畫出“一個 token 的 K 行 → 1024 int8 8 個 float scale”的落盤/落存圖。預期輸出你能算清 f16→q8 KV 省多少字節、scale 為什么按“每 token 每頭”、以及 f32 KV 為何只是調試探針。收尾本篇源碼點名vllm_safetensors.cq8 KV 分配與開關第 8208–8244 行、per-head 量化寫入第 9466–9476 行。開源倉庫Kestrel-LLM (Gitee)源碼可得雙許可學習 / 學術研究免費下篇預告q8 KV 存好了decode 怎么讀它才最省下一篇 9-2 進flash_attn_single_q_q8_neon——量化 Q、在線 rescale、一條路徑掃完全部 KV。關鍵詞q8 KV、KV cache、INT8 量化、帶寬、decode上一篇Day 8·3 KV Cache按頭存儲vs按token存儲內存布局下一篇Day 9·2 flash_attn_single_q_q8_neon——單 q 單遍掃全 KV