ik_llama.cpp 行交错量化解析:IQ3_S_R4 如何把 sub-4bpw i-quants 的 CPU 性能提升近一倍
2026/9/19 16:57:50 网站建设 项目流程

ik_llama.cpp 行交错量化解析:IQ3_S_R4 如何把 sub-4bpw i-quants 的 CPU 性能提升近一倍

【免费下载链接】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 #162(IQ3_S_R4)为切入点,讲解该项目为解决 sub-4 bpw(bits-per-weight)i-quants 量化类型在 CPU 上矩阵乘性能低下而引入的行交错(row-interleaved)重打包思路:在不改变权重位宽的前提下,通过把IQ3_S的权重按 4 行交错重新布局,换取向量化与缓存友好度的大幅提升。读完本文,你将理解 R4 系量化类型的来历、它在 ggml.h 与 llama-quantize.cpp 中的落地方式、-rtr/--run-time-repack运行时重打包参数的正确用法与限制,以及 PR 162 给出的三平台实测性能数据。


一、背景:为什么 sub-4 bpw 的 i-quants 在 CPU 上"跑不动"

在 ik_llama.cpp 的量化体系中,IQ3_S属于i-quants(improved quants)家族,名义位宽 3.44 bpw(见 quantize.cpp 中的类型描述),它比传统 k-quants 更依赖码本(codebook)查表与非线性编码来压缩权重。

PR #162 的出发点非常直白:"Sub-4 bpw i-quants have a terrible CPU performance"(低于 4 bpw 的 i-quants 在 CPU 上性能很差)。原因从实现结构上可以推断:极低位宽意味着每个 block 中打包了大量细粒度比特信息,解包时指令密度高、内存访问模式碎片化,导致 SIMD 向量化效率低、缓存利用率差。这在 prompt processing(PP,即预填充阶段的大矩阵乘法 GEMM)中体现得尤为明显,因为 PP 是典型的计算密集型负载,SIMD 吞吐直接决定吞吐量。

作者因此产生了一个直觉:如果对权重行做交错(interleaving rows)重排,是否能把性能救回来?于是就有了 PR #162 的核心产物——IQ3_S_R4

二、什么是 R4:对 IQ3_S 的 4 行交错重打包

IQ3_S_R4不是一种新的压缩算法,而是IQ3_S权重的 4 行交错(4-row interleaved)重打包版本。这一点在仓库中有三处相互印证的证据:

  1. 类型定义:在 ggml.h 中,GGML_TYPE_IQ3_S_R4 = 221GGML_TYPE_IQ1_S_R4 = 219等并列,属于独立的张量类型枚举;对应文件类型GGML_FTYPE_MOSTLY_IQ3_S_R4 = 220(见 ggml.h)。

  2. 重打包映射表:在 llama-quantize.cpp 的interleaved_properties()中,有一个全局映射表记录每个交错类型对应的基础类型与交错行数:

{ GGML_TYPE_IQ3_S_R4, { GGML_TYPE_IQ3_S, 4} }, // 基础类型 IQ3_S,4 行交错 { GGML_TYPE_IQ1_S_R4, { GGML_TYPE_IQ1_S, 4} }, { GGML_TYPE_IQ2_K_R4, { GGML_TYPE_IQ2_K, 4} }, { GGML_TYPE_IQ4_KS_R4, { GGML_TYPE_IQ4_KS, 4} }, ...
  1. 量化工具声明:在 quantize.cpp 中,IQ3_S_R4被直接描述为"IQ3_S repacked",位宽仍保持 3.44 bpw——即存储成本不变,只是数据布局改变

其原理可以概括为:把多个相邻行的量化数据按行交错方式重新排列,使得 GEMM 内核在加载权重块时能一次取到更多连续有效数据、更好地利用 SIMD 寄存器与缓存行。类似的 R4 族还包括IQ4_KS_R4IQ2_K_R4IQ3_K_R4IQ4_K_R4IQ5_K_R4等(详见 README.md 的量化列表),而 PR #162 是这一思路在 sub-4 bpw i-quants 上的首次验证。

三、实测性能:PP-512 与 TG-128 三平台数据(PR #162 原文)

PR #162 给出了在 LLaMA-3.1-8B 上、三大 CPU 平台的完整基准数据。以下数据直接继承自该 PR 的 Description,单位均为 tokens/s(数值格式为均值 ± 标准差)。

3.1 Prompt Processing(PP-512):核心收益场景

平台线程数IQ3_SIQ3_S_R4加速比
ARM_NEON(M2-Max)842.97 ± 1.2880.61 ± 0.411.876
Zen4(Ryzen-7950X)16104.66 ± 0.68159.08 ± 0.571.520
AVX2(Ryzen-5975WX)32132.50 ± 0.37231.41 ± 0.451.746

PP 阶段收益显著:ARM_NEON 接近 1.9 倍,AVX2 约 1.75 倍,即使本身吞吐已很高的 Zen4 也有 1.52 倍。这与前面分析的"GEMM 对数据布局敏感"的推断一致——交错布局直接提升了矩阵乘的向量化效率。

3.2 Token Generation(TG-128):多线程扩展下的收益

TG(自回归解码)阶段是 GEMV(矩阵-向量乘)负载,瓶颈更偏向访存带宽,因此收益普遍小于 PP,但依然可观,尤其 AVX2:

平台线程数IQ3_SIQ3_S_R4加速比
ARM_NEON23.00 ± 0.003.40 ± 0.001.133
ARM_NEON45.74 ± 0.026.60 ± 0.011.150
ARM_NEON89.25 ± 0.8312.27 ± 0.331.326
Zen424.17 ± 0.004.38 ± 0.011.050
Zen447.82 ± 0.058.14 ± 0.011.041
Zen4814.29 ± 0.0214.41 ± 0.021.008
AVX221.98 ± 0.003.31 ± 0.001.672
AVX243.87 ± 0.006.49 ± 0.001.677
AVX287.13 ± 0.0111.63 ± 0.021.631
AVX21612.97 ± 0.0015.81 ± 0.001.219

规律清晰:AVX2 平台受益最大(TG 加速 1.2~1.7 倍),ARM_NEON 次之,Zen4 在 TG 阶段几乎无增益(约 1.0 倍),这是因为 Zen4 的 AVX-512 原生吞吐已足够高,GEMV 的访存瓶颈盖过了布局优化收益。这也提醒使用者:R4 收益与平台、负载类型强相关,PP 是它的主战场。

四、仓库落地:从类型定义到运行时重打包

IQ3_S_R4在仓库中并非孤立实验,而是完整的工程链路:

4.1 张量类型与文件类型

  • 张量类型GGML_TYPE_IQ3_S_R4与文件类型GGML_FTYPE_MOSTLY_IQ3_S_R4定义于 ggml.h。
  • GEMM 内核在 iqk_gemm_iquants.cpp 与 iqk_gemm_iquants.cpp 中为该类型提供专门的矩阵乘分支;相关量化/解包逻辑分布在 ggml-quants.c 及 iqk 目录 中。
  • 模型加载时,llama-model-loader.cpp 与 llama-model.cpp 均注册了该类型的处理路径。

4.2 两种使用方式

方式一:直接量化/重打包。使用llama-quantize工具把模型输出为IQ3_S_R4类型(或对已有 IQ3_S 模型做纯重打包):

# 直接从 f16 模型量化为 IQ3_S_R4(3.44 bpw) llama-quantize /models/model-f16.gguf /models/model-iq3-s-r4.gguf IQ3_S_R4 # 或先量化为 IQ3_S,再重打包 llama-quantize /models/model-f16.gguf /models/model-iq3-s.gguf IQ3_S llama-quantize /models/model-iq3-s.gguf /models/model-iq3-s-r4.gguf IQ3_S_R4

llama-quantize的完整类型清单见 quantize.cpp,其中IQ3_S_R4描述为"IQ3_S repacked"

方式二:运行时重打包(-rtr)。无需重新生成模型文件,在推理时通过-rtr, --run-time-repack参数让加载器把支持的量化类型自动重打包为行交错格式(见 parameters.md):

llama-cli -m /models/model.gguf -rtr

注意:-rtr是 ik_llama.cpp独有参数(见 parameters.md 中 "Unique parameters" 一节),并非 llama.cpp 上游能力。

4.3 重要限制:混合 CPU/GPU 推理时慎用-rtr

README.md 给出了明确警告:如果 MoE 模型采用混合 CPU/GPU 推理且部分专家留在 CPU 上,不要使用-rtr,除非你清楚自己在做什么。原因有二:

  1. -rtr会把留在 RAM 中的所有张量在加载时重打包为行交错格式;
  2. 并非所有量化类型都有行交错的 CUDA 实现(典型如Q2_K、Q3_K、Q4_K、Q5_K、Q6_K等 k-quants 缺少 CUDA 行交错内核)。

一旦张量被重打包而 GPU 侧没有对应内核,这些张量的矩阵乘将永远只能在 CPU 上执行——即使原本可以更优地卸载到 GPU,最终反而导致 prompt processing 变慢。换句话说:-rtr适合纯 CPU 推理或张量确实驻留 CPU 的场景,在异构卸载场景下必须谨慎评估。

五、后续演进:R4 思路与"超快 CPU PP"的汇合

PR #162 于 2024-12-23 提交后被关闭(State: Closed),但行交错思路在 ik_llama.cpp 中持续生长:README 中记录了后续大量同族实现,例如IQ4_KS_R4(PR 150)、IQ2_K_R4(PR 146)、IQ3_K_R4(PR 145)、IQ4_K_R4(PR 138)、IQ4_KSS(PR 89)等,CUDA 端也陆续补齐了IQ1_S_R4(PR 492)、IQ1_M_R4(PR 494)、IQ4_KS_R4 / IQ5_KS_R4(PR 493)等内核。

更重要的是,PR #515 / #531 提出了"对所有非交错量化类型大幅加速 CPU prompt processing"的新方案,并经由后续多个 PR 推广到全部量化类型与三个受支持的 CPU 平台(Zen4 / AVX2 / NEON,见 README.md)。从代码结构看,可以推断:R4 系交错布局与"非交错类型本身提速"两条路线在仓库中是并行演进的——前者通过布局换取收益,后者则直接优化解包与向量化路径;两者最终都指向同一个目标:让低比特量化在 CPU 上真正可用。

六、小结:何时选择 IQ3_S_R4

结合 PR #162 的实测数据与仓库实现,可给出如下实用判断:

  • 优先使用场景:纯 CPU 推理、以 prompt processing 为主的工作负载(长上下文预填充、批量推理),此时IQ3_S_R4相比IQ3_S可获 1.5~1.9 倍 PP 加速,而位宽不变(仍为 3.44 bpw),是"零精度代价换性能"的布局优化;
  • 收益有限场景:Zen4 平台的 TG 阶段收益接近 1.0 倍,若你的负载以长流式生成为主,收益将不明显;
  • 慎用场景:混合 CPU/GPU 卸载推理——除非确认相关张量没有 GPU 行交错内核的兼容性问题,否则避免-rtr自动重打包;
  • 工程入口:类型定义见 ggml.h,重打包映射见 llama-quantize.cpp,量化命令见 quantize.cpp,运行时参数见 parameters.md。

一句话总结:IQ3_S_R4 证明了"不改精度、只改布局"也能在 CPU 上释放近一倍的算力,它是理解 ik_llama.cpp 整个 R4 量化家族与-rtr运行时重打包机制的绝佳起点。

【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询