、性能提升與使用指南)
ik_llama.cpp 的 Q6_K_R4 行交錯量化源碼實現(xiàn)、性能提升與使用指南【免費下載鏈接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance項目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp導(dǎo)讀本文基于 ik_llama.cpp 的 PR #130「Q6_K_R4」系統(tǒng)解析一種新型行交錯row-interleaved量化格式在保持Q6_K精度特征的前提下將相鄰 4 行數(shù)據(jù)交錯重排從而讓 ARM_NEON、Zen4/AVX2 等 SIMD 后端的矩陣乘GEMM與向量點積GEMV實現(xiàn)獲得大幅加速。你將了解到該格式在源碼中的完整落地方式量化、重打包、類型注冊、向量點積掌握如何在當前倉庫中通過llama-quantize把模型轉(zhuǎn)換為Q6_K_R4并理解 PR 中給出的 PP-512 與 TG-128 實測數(shù)據(jù)的真實含義與適用邊界。一、背景為什么需要 Q6_K_R4Q6_K是 llama.cpp 體系中塊大小為 256QK_K的 K 系量化類型長期被用于模型的核心張量。正如 PR #130 開篇所指出的If nothing elseQ6_Kis routinely used for the output tensor, so having a betterQ6_Kperformance would be useful.即即使其他張量不使用Q6_K模型的output tensor輸出張量也通常會采用Q6_K來保證最終 logits 的精度因此提升Q6_K的計算性能對幾乎所有量化模型都有實際收益。Q6_K_R4并不是一種新的比特率量化方案而是行交錯row-interleaved內(nèi)存布局優(yōu)化把 4 行Q6_K塊的數(shù)據(jù)按 SIMD 友好的方式交錯排列使 CPU 后端尤其是 ARM_NEON、AVX2/Zen4的 GEMM/GEMV 內(nèi)層循環(huán)能以更少的加載、更連續(xù)的內(nèi)存訪問完成計算。它屬于 PR #118~#123、#129 這一系列 R44 行交錯量化工作的延續(xù)——之前已覆蓋Q4_0_R4、Q8_0_R4、Q5_0_R4、Q6_0_R4、IQ4_XS_R4、Q4_K_R4等PR #130 則是把同一思路應(yīng)用到Q6_K上。二、源碼中的實現(xiàn)細節(jié)2.1 類型注冊與基礎(chǔ)屬性在 ggml/include/ggml.h 中GGML_TYPE_Q6_K_R4 214被注冊為獨立的量化類型對應(yīng)的文件格式標記為GGML_FTYPE_MOSTLY_Q6_K_R4 214except 1d tensors即除一維張量外的所有張量均使用該格式。在 ggml/src/ggml.c 中該類型的核心屬性如下屬性值說明type_nameq6_k_r4GGUF 與命令行中使用的名稱blck_sizeQK_K256塊大小與原Q6_K一致type_sizesizeof(block_q6_K)單行塊大小與原類型一致不額外占用空間is_quantizedtrue屬于量化類型to_floatdequantize_row_q6_k_r4反量化入口from_floatquantize_row_q6_k_r4量化入口vec_dotvec_dot_q6_k_r4_q8_k向量點積與Q8_K激活配合vec_dot_typeGGML_TYPE_Q8_K激活向量按Q8_K量化nrows/row_meta_size1/0單行元數(shù)據(jù)值得強調(diào)的是type_size與原Q6_K完全相同——R4 重排不增加任何存儲開銷純收益來自更優(yōu)的訪存與計算布局。2.2 量化與重打包實現(xiàn)量化入口quantize_q6_k_r4位于 ggml/src/iqk/iqk_quantize.cpp。其策略是先按標準Q6_K逐行量化再執(zhí)行 4 行重打包auto q_func [] (const float * x, void * vy, int n_per_row, const float * imatrix, [[maybe_unused]] const quantize_user_data * user_data) { quantize_q6_K(x, (char *)vy, 1, n_per_row, imatrix, user_data); }; return quantize_repack16, block_q6_K, block_q6_k_r4, 4(GGML_TYPE_Q6_K, src, dst, nrows, n_per_row, imatrix, user_data, q_func, repack_q6_k);即通過模板quantize_repack16, block_q6_K, block_q6_k_r4, 4以 16 行為一組、4 行為一步進行重排。核心重排函數(shù)repack_q6_kiqk_quantize.cpp完成三件事斷言約束nrows % 4 0且n_per_row % QK_K 0要求行數(shù)與每行塊數(shù)都能被 4 整除元數(shù)據(jù)d/scale交錯將 4 行中同一位置塊的d全局縮放與scales子塊縮放按交錯索引寫入目標塊block_q6_k_r4形成y[ibl].d[k]、y[ibl].scales[8*ibk0/4]的布局量化值交錯對每個 6-bit 量化值通過convert_q6_k拆分為 4-bit 低位ql與高位qh再將 4 行中同一位置的低位/高位按位打包進y[ibl].ql[64*ib4*ki...]與y[ibl].qh[32*ib4*ki...]。反量化dequantize_row_q6_k_r4則按n_per_row k/4切分 4 個輸出行指針逐塊還原。這種逐行量化 重排的路徑有一個工程上的好處量化的數(shù)值結(jié)果與標準Q6_K完全一致只是布局不同因此在精度上沒有任何妥協(xié)可以直接復(fù)用已有的Q6_K量化質(zhì)量。2.3 向量點積與多后端適配vec_dot綁定為vec_dot_q6_k_r4_q8_k即 R4 權(quán)重與Q8_K激活的逐塊點積。它在多個后端均有實現(xiàn)CPU 通用路徑注冊于 ggml/src/ggml.cIQK 優(yōu)化路徑在 ggml/src/iqk/iqk_mul_mat.cpp 的 GEMM/GEMV 調(diào)度中GGML_TYPE_Q6_K_R4被顯式列入支持列表如第 338、376、890、988 行等處走iqk_mul_mat的快路徑CUDA 路徑在 ggml/src/ggml-cuda.cu 中GGML_TYPE_Q6_K_R4被映射為 4 路展開{ GGML_TYPE_Q6_K_R4, 4 }并在第 1216 行附近被納入支持 MMQ/GEMV 的 R4 類型集合。也就是說Q6_K_R4從 CPUNEON/AVX2/Zen4到 CUDA 的推理鏈路是完整的這與 PR #127Q4_0_R4 on CUDA之后形成的R4 全平臺支持路線一致。2.4 運行時重打包repack能力除靜態(tài)量化外倉庫還支持在運行時把標準張量重打包為 R4 布局。在 iqk_quantize.cpp 的重打包注冊表中{ GGML_TYPE_Q6_K, { GGML_TYPE_Q6_K_R4, 4, (Repack::repack_func)repack_q6_k } },即運行時可把GGML_TYPE_Q6_K張量在線重打包為Q6_K_R44 行交錯并可使用-ot/--override-tensor相關(guān)機制指定對哪些張量生效參見 PR #272、#274 的后續(xù)工作。這為下載標準Q6_K模型、加載時按需轉(zhuǎn) R4的工作流提供了支持而無需重新量化整個模型。三、性能表現(xiàn)PR #130 的實測數(shù)據(jù)PR #130 使用 LLaMA-3.1-8B 模型在三種 CPU 平臺、兩種場景下對比了Q6_K與Q6_K_R4。以下數(shù)據(jù)均引自 github-data/pull_requests/130 - Q6_K_R4.md測量單位均為 tokens/s。3.1 Prompt 處理PP-512512 token 的 prompt 批量處理平臺線程數(shù)Q6_KQ6_K_R4加速比ARM_NEONM2-Max857.57 ± 0.6183.25 ± 0.811.446Zen4Ryzen-7950X16195.20 ± 0.74243.25 ± 0.311.246AVX2Ryzen-5975WX32194.51 ± 0.35264.16 ± 0.441.358可以看到 PP 場景下三個平臺均有顯著收益其中ARM_NEON 提升最大約 44.6%AVX2 約 35.8%Zen4 約 24.6%。3.2 Token 生成TG-128平臺線程數(shù)Q6_KQ6_K_R4加速比ARM_NEON27.46 ± 0.037.35 ± 0.010.985ARM_NEON413.88 ± 0.0213.80 ± 0.010.994ARM_NEON818.31 ± 0.1618.57 ± 0.141.014Zen415.38 ± 0.007.94 ± 0.001.476Zen428.93 ± 0.0010.38 ± 0.001.162Zen449.97 ± 0.2710.18 ± 0.011.021AVX224.75 ± 0.005.78 ± 0.011.217AVX247.57 ± 0.008.47 ± 0.001.119AVX288.23 ± 0.009.14 ± 0.001.111TG 場景的結(jié)論需要細分Zen4 / AVX2 全面受益即使線程數(shù)較少也有 1.1~1.5 倍提升。PR 特別指出With this Zen4 implementation, for TG the available memory bandwidth is fully saturated with just 2 threads!——即 Zen4 實現(xiàn)只需2 個線程就能打滿可用內(nèi)存帶寬這解釋了為何單線程 TG 能獲得 1.476 倍的最大加速比ARM_NEON 基本持平2~4 線程時略有回退0.985~0.9948 線程時略升1.014。PR 原文也明確說明了這一例外Except on ARM_NEON, where TG performance is slightly lower for small numbers of threads。四、如何生成與使用 Q6_K_R4 模型4.1 使用 llama-quantize 轉(zhuǎn)換在examples/quantize/quantize.cpp的量化類型表中Q6_K_R4被注冊為{ Q6_K_R4, LLAMA_FTYPE_MOSTLY_Q6_K_R4, Q6_K repacked, },因此可以用與其它類型完全一致的方式量化# 從已有 GGUF 重新量化為 Q6_K_R4 ./llama-quantize --allow-requantize model.gguf model-q6_k_r4.gguf Q6_K_R4 # 或直接指定輸出類型結(jié)合 imatrix 提升量化質(zhì)量 ./llama-quantize --imatrix imatrix.dat model.gguf model-q6_k_r4.gguf Q6_K_R4轉(zhuǎn)換完成后可直接交給llama-cli、llama-server等運行時加載推理。Q6_K_R4的blck_size與Q6_K相同256因此不需要額外的對齊處理即可用于標準矩陣乘。4.2 運行時重打包無需重新量化如果你已經(jīng)持有標準Q6_K模型可以通過運行時的張量重打包機制見上文 2.4 節(jié)的注冊表按需轉(zhuǎn)為 R4 布局而無需重新量化整份模型文件。具體張量選擇可通過 tensor 名稱正則表達式控制適合只想加速 output tensor 等特定張量的場景。4.3 適用前提與注意事項精度無損由于 R4 只是布局重排、數(shù)值路徑與原Q6_K完全一致無需重新評估困惑度perplexity平臺差異PP 場景所有平臺都受益TG 場景 Zen4/AVX2 顯著受益、ARM_NEON 小線程數(shù)基本持平是否啟用取決于你的硬件與主要負載類型編譯開關(guān)R4 的 CPU 快路徑依賴項目的 IQK 相關(guān)實現(xiàn)iqk_mul_mat構(gòu)建時請保持默認的量化/矩陣乘組件完整編譯參見 ggml/src/iqk 目錄行數(shù)約束重打包要求nrows % 4 0且n_per_row % QK_K 0絕大多數(shù)模型張量滿足該條件一維張量如 token embeddings 之外的偏置類張量不受影響因為文件格式標記為 except 1d tensors。五、在 R4 系列中的定位Q6_K_R4并非孤立存在它是 ik_llama.cpp 2024 年末構(gòu)建的R4 行交錯量化體系的一部分。完整脈絡(luò)包括塊級 R4 先行PR #118~#123、#125~#128 完成了IQ4_NL_R4、Q4_0_R4、Q8_0_R4、Q5_0_R4、Q6_0_R4、IQ4_XS_R4以及 ARM_NEON/CUDA 上的相應(yīng)實現(xiàn)K 系 R4 跟進PR #129Q4_K_R4、#130Q6_K_R4、#132Q5_K_R4、#134Q3_K_R4、#136Q2_K_R4逐步補齊 K 系I 系 R4 深化PR #138、#145、#146、#149、#150 等把 R4 布局擴展到IQ4_K、IQ3_K、IQ2_K、IQ5_K、IQ4_KS等 I 系類型后續(xù)演進PR #189 之后部分類型進一步演進為 8 行交錯_R8PR #272、#274 引入運行時重打包與張量正則選擇能力。從源碼結(jié)構(gòu)看這一體系的核心收益機制是統(tǒng)一的通過把多行數(shù)據(jù)交錯到同一緩存行/寄存器批次內(nèi)減少 SIMD 內(nèi)層循環(huán)的訪存開銷并提升內(nèi)存帶寬利用率。Q6_K_R4作為其中唯一被 routinely used for the output tensor 的類型具有最普適的實戰(zhàn)價值。結(jié)語Q6_K_R4是 ik_llama.cpp 在不改變量化語義、僅重排內(nèi)存布局這一約束下做出的典型性能優(yōu)化數(shù)值路徑與標準Q6_K完全一致卻在 PP-512 場景為 ARM_NEON 帶來約 1.45 倍、AVX2 約 1.36 倍、Zen4 約 1.25 倍的加速在 TG 場景Zen4 單線程可達 1.48 倍并僅需 2 線程即可飽和內(nèi)存帶寬。對于任何以Q6_K作為輸出張量或整體權(quán)重量化的模型部署切換到Q6_K_R4都是低成本、高回報的一步?!久赓M下載鏈接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance項目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考