拓冰建站拓冰建站
首页 / 资讯中心 / 正文

ik_llama.cpp IQ4_K_R4 量化格式详解:AVX2/Zen4 上的 R4 重排加速与性能提升

ik_llama.cpp IQ4_K_R4 量化格式详解AVX2/Zen4 上的 R4 重排加速与性能提升【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp导读本文基于 ik_llama.cpp 仓库中 PR #144「Slightly faster IQ4_K_R4 on AVX2/Zen4」 展开讲解该仓库独有的R44 行重排row-repacked量化格式中IQ4_K_R4的原理、实现与性能收益。读完本文你将理解什么是 R4 重排、IQ4_K_R4相比IQ4_K为何能提升矩阵乘性能、PR #144 在 AVX2/Zen4 上又做了哪些加速以及如何用llama-quantize生成和实测该格式。一、背景从 IQ4_K 到 IQ4_K_R4IQ4_K是 ik_llama.cpp 在标准 k-quants 基础上引入的「非线性non-linear量化」格式族成员约 4.5 bpwbits per weight。在 examples/quantize/quantize.cpp 中可以确认它被描述为 4.5 bpw non-linear quantization而IQ4_K_R4的描述是IQ4_K repacked——即对IQ4_K数据重新打包后的变体。为什么要重排repack这要从矩阵乘的计算模式说起。llama.cpp的mul_mat中权重量化块block通常按「一行一个 block」的布局存储即block_iq4_k每块覆盖一行中QK_K个权重。计算时每个 block 需要先**解包unpack**才能与激活值做点积。解包 k-quants/i-quants 的位运算代价高昂因此在解包之后应尽量让它与右侧矩阵激活的多个列相乘摊薄解包开销但累积结果必须能留在向量寄存器中所以参与相乘的列数存在上限。R4 格式的解法是把相邻 4 行中同一位置的 4 个 block 打包成一个超级 block让一次解包同时服务 4 行、且权重量化数据在内存中按更利于 SIMD 加载的顺序排列。从源码看ggml/src/ggml-common.h 定义了block_iq4_k_r4typedef struct { ggml_half d[4]; // 4 行各自的 scalefp16 uint8_t extra[8]; // 4 行各 2 个 extra 标志位每组是否使用高 16 个值 uint8_t scales_h[QK_K/16]; // 4 行合并后的 scale 高 2 位 uint8_t scales_l[QK_K/8]; // 4 行合并后的 scale 低 4 位 uint8_t qs[QK_K*2]; // 4 行合并后的量化权重 } block_iq4_k_r4; static_assert(sizeof(block_iq4_k_r4) 4*sizeof(block_iq4_k), wrong iq4_k_r4 block size/padding);关键点sizeof(block_iq4_k_r4) 4 * sizeof(block_iq4_k)即 R4 格式不增加任何存储开销纯粹是布局变换内存占用与原IQ4_K完全一致只是把 4 行数据交错打包便于向量化取数和复用解包结果。二、PR #144 做了什么AVX2/Zen4 上的进一步提速PR #138「IQ4_K_R4」 首次实现了IQ4_K_R4当时的结论是ARM_NEON 上收益非常显著而 AVX2/Zen4 上收益较小作者自评「AVX2/Zen4 的实现可能不是最优」。PR #144「Slightly faster IQ4_K_R4 on AVX2/Zen4」 正是针对这一短板做的后续优化核心目标就是专门打磨 AVX2/Zen4 的IQ4_K_R4计算路径。该 PR 由仓库作者 ikawrakow 提交于 2024-12-16 创建并关闭Closed即已合入主干说明中给出 LLaMA-3.1-8B、PP-512512 token 的 prompt processing即预填充阶段的实测平台优化前PR #144 后Ryzen-7950XZen4232 t/s251 t/sRyzen-5975WXAVX2227 t/s249 t/s即 Zen4 提升约8.2%AVX2 提升约9.7%把之前「AVX2/Zen4 上 R4 收益小」的短板补上了一大块。结合 PR #138 的基线Zen4 16 线程 182.2 → 232.63 t/sAVX2 32 线程 206.43 → 227.60 t/s整个 R4 化过程在 Zen4 上累计从 182.2 t/s 提升到 251 t/s约 1.38 倍AVX2 上从 206.4 t/s 提升到 249 t/s约 1.21 倍。PR #144 之所以效果明显从仓库的实现结构可以推断IQ4_K_R4的矩阵乘走的是iqk_mul_matiqk 后端它针对不同 SIMD 架构维护了独立的 kernel 集合详见下文第三节AVX2/Zen4 的 kernel 在 PR #144 中得到重写/调优后才追上了 NEON 的水平。三、源码级原理iqk 后端如何加速 IQ4_K_R43.1 编译开关GGML_USE_IQK_MULMATIQ4_K_R4的加速依赖 iqk 后端。在 ggml/src/iqk/iqk_quantize.cpp 中vec_dot_iq4_k_r4_q8_k优先尝试 iqk 路径void vec_dot_iq4_k_r4_q8_k(int n, float * s, size_t bs, const void * vx, size_t bx, const void * vy, size_t by, int nrc) { #if GGML_USE_IQK_MULMAT if (iqk_mul_mat(1, 1, n, GGML_TYPE_IQ4_K_R4, vx, 0, GGML_TYPE_Q8_K, vy, 0, s, 0, 0, 1)) { return; } #endif ... }也就是说编译时开启GGML_USE_IQK_MULMAT后IQ4_K_R4与Q8_K的点积会路由到iqk_mul_mat若未开启该宏则回退到普通路径。3.2 按架构分派 kernelAVX2/Zen4 与 ARM_NEON 两条路线iqk_mul_mat的 kernel 分派在 ggml/src/iqk/iqk_mul_mat.cpp 中体现GGML_TYPE_IQ4_K_R4与IQ2_K_R4、IQ3_K_R4、IQ5_K_R4、IQ4_KS_R4、IQ5_KS_R4等一同归入iqk_set_kernels_iqk_quants这一组。而该文件以#ifdef __aarch64__为界划分了两大实现分支x86AVX2/AVX-512/Zen4与 ARMNEON各有独立的 kernel 选择逻辑这正是 PR #138 中「NEON 收益大、x86 收益小」、以及 PR #144「专门优化 x86」得以成立的结构基础。3.3 R4 重排的量化实现量化侧的核心在 ggml/src/iqk/iqk_quantize.cppquantize_iq4_k_r4先把 4 行数据按普通IQ4_K量化再调用repack_iq4_k重排为 R4 布局size_t quantize_iq4_k_r4(const float * src, void * dst, int64_t nrows, int64_t n_per_row, const float * imatrix, [[maybe_unused]] const quantize_user_data * user_data) { GGML_ASSERT(nrows%4 0); GGML_ASSERT(n_per_row%QK_K 0); char * qcur (char *)dst; auto row_size ggml_row_size(GGML_TYPE_IQ4_K, n_per_row); std::vectorchar qtmp(4*row_size); for (int row 0; row nrows; row 4) { quantize_iq4_k(src, (void *)qtmp.data(), 4, n_per_row, imatrix, user_data); repack_iq4_k(4, n_per_row, (const block_iq4_k *)qtmp.data(), (block_iq4_k_r4 *)qcur, false); qcur 4*row_size; src 4*n_per_row; } return nrows*row_size; }repack_iq4_kiqk_quantize.cpp逐 block 地把 4 行的dscale、extra、scales_l/scales_h、以及 16 个 4-bit 权重按位交错合并进block_iq4_k_r4的qs[QK_K*2]中。反量化函数dequantize_row_iq4_k_r4iqk_quantize.cpp则按同样布局读回 4 行浮点值保证格式可逆、数值等价于普通IQ4_K。由于重排是纯布局变换IQ4_K_R4与IQ4_K的量化精度完全一致提速不牺牲质量。3.4 行数与列数的权衡R4 系列的通用加速逻辑值得说明的是R4 提速并非IQ4_K_R4独有。从 iqk_mul_mat.cpp 的num_rows()可以看到IQ2_K_R4、IQ3_K_R4、IQ4_K_R4、IQ5_K_R4等大量 R4 类型都声明为每超级块 4 行return 4而IQ4_XS_R8、Q8_K_R8等则是 8 行return 8、Q8_K_R16是 16 行。行数越多一次解包可复用的机会越多但寄存器压力也越大因此作者针对不同量化格式选择了不同的重排行数。在 PR #157「R4 i-quants improvements」 中作者进一步解释了这一权衡解包IQ2_XXS、IQ2_XS、IQ2_S、IQ3_XXS的代价极高值得把累积结果在「寄存器 ↔ 内存」间搬进搬出以便让解包结果被复用超过 8 次因此该 PR 把列数从 8 提升到 16。这也说明 R4 系列的性能调优始终围绕「解包成本 vs 寄存器容量」这一核心矛盾展开PR #144 正是这条优化路线在 AVX2/Zen4 上的延续。四、实战如何量化出 IQ4_K_R4 并验证性能4.1 用 llama-quantize 生成 IQ4_K_R4IQ4_K_R4是 GGUF 中注册的标准新类型参见 gguf-py/gguf/constants.py 中的映射可直接通过仓库的量化工具生成。用llama-quantize源码位于 examples/quantize/quantize.cpp# 查看支持的类型列表确认包含 IQ4_K_R4 ./build/bin/llama-quantize --help # 将 fp16 模型量化为 IQ4_K_R4 ./build/bin/llama-quantize ./models/llama-3.1-8b-f16.gguf ./models/llama-3.1-8b-iq4_k_r4.gguf IQ4_K_R4类型表中IQ4_K_R4对应的 ftype 为LLAMA_FTYPE_MOSTLY_IQ4_K_R4描述为IQ4_K repackedquantize.cpp量化后文件大小与IQ4_K相当约 4.5 bpw因为 R4 只是重排、不增加存储。4.2 开启 iqk 后端与性能验证编译时确保以GGML_USE_IQK_MULMAT构建iqk 后端默认启用使vec_dot_iq4_k_r4_q8_k走iqk_mul_mat快速路径iqk_quantize.cpp。运行时用 examples/main/main.cpp 或llama-bench做 PPprompt processing与 TGtoken generation基准测试。PR 中使用的指标是PP-512512 token 预填充吞吐单位 t/s实测模型为 LLaMA-3.1-8B。平台差异如 PR #138 表格所示同一模型在 ARM_NEONM2-Max上 IQ4_K → IQ4_K_R4 可获约 1.86 倍 PP 提速Zen4 约 1.28 倍AVX2 约 1.10 倍详见 PR #138TG 阶段TG-128在低线程数下同样有明显收益如 AVX2 2 线程 1.72 倍线程数增多后收益缩小。而 PR #144 之后x86 的 PP 数据进一步提升到 251/249 t/s。这些数字均为仓库文档记录的实测结果实际性能取决于 CPU 型号、线程数与内存带宽建议在目标机器上自行复测。4.3 与 CUDA 等其他后端的对照IQ4_K_R4并非只有 CPU 路径。在 ggml/src/ggml-cuda/template-instances/mmq-instance-iq4_k_r4.cu 和 mmvq-instance-iq4_k_r4.cu 中存在对应的 CUDA kernel 实例相关实现见 README.md 中记录的 PR 461说明该格式在 GPU 后端同样有 mmq/mmvq 支持。本文聚焦 CPU 侧 AVX2/Zen4 的加速若关注 GPU可查看上述模板实例继续深入。五、总结IQ4_K_R4是 ik_llama.cpp 对IQ4_K约 4.5 bpw 非线性量化的4 行重排变体存储开销与IQ4_K完全一致数值精度等价。R4 的核心价值在于将解包好的权重与右侧矩阵的多个列复用相乘摊薄昂贵的解包成本block_iq4_k_r4将 4 行数据交错打包ggml-common.h配合 iqk 后端按架构分派的 kerneliqk_mul_mat.cpp实现加速。PR #144 专门优化了此前偏弱的 AVX2/Zen4 路径PP-512LLaMA-3.1-8B从 232/227 t/s 提升到251/249 t/s补上了 PR #138 之后 x86 侧相对 NEON 的差距。结合 PR #157 的 16 列复用改进可以看出R4 系列量化在 ik_llama.cpp 中是一条持续演进、以「解包复用」为纲的 CPU 推理加速技术路线IQ4_K_R4是其中收益最直观的代表之一。如果想在真实硬件上复现文中的数字可以按第四节的方式用仓库自带的llama-quantize生成IQ4_K_R4模型再用llama-bench/main对比IQ4_K与IQ4_K_R4的 PP、TG 吞吐亲身体验这套重排优化带来的实际收益。【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门