
ik_llama.cpp IQ1_S_R4 量化解析1.5 bpw 四行交织低比特量化与 DeepSeek 极低比特部署实战【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp导读IQ1_S_R4是 ik_llama.cpp 在 2025 年 2 月通过 PR #185 引入的全新低比特量化类型它是IQ1_S的4 行交织4-row interleaved变体将每权重比特数从 1.5625 bpw 进一步压缩到1.5 bpw同时把量化块大小缩小到 32从而解决了 DeepSeek 系模型中大量张量行数不能被 256 整除、被迫回退到更高比特IQ4_NL的痛点。本文以 PR #185 的完整描述与讨论为骨架结合当前仓库源码ggml、src/llama-quantize.cpp、examples/quantize/quantize.cpp为你讲解IQ1_S_R4的设计原理、MoE 量化混合规则、CPU 实测性能并给出可复现的 DeepSeek-R1 极低比特量化实战命令与量化日志解读方法。一、背景为什么需要 sub-2 bpw 量化1.1 DeepSeek 热浪下的极低比特需求PR #185 的出发点非常直接DeepSeek 系列模型尤其是 DeepSeek-R1引爆了社区对sub-2 bpw每权重比特数低于 2量化的热情Unsloth 使用IQ1_S/IQ1_M对 DeepSeek-R1 做了极低比特量化并广受关注。PR 作者 ikawrakow 在描述中直言Given the hype around DeepSeeks models and Unsloths sub-2 bpw quantization of DeepSeek-R1 usingIQ1_S/IQ1_M, I decided to give some love to sub-2 bpw quants.也就是说IQ1_S_R4的目标场景非常明确把 600B 级别的巨型 MoE 模型压缩到单卡甚至纯 CPU 可承载的尺寸。1.2 IQ1_S 的两个结构性缺陷作者没有简单复刻IQ1_S而是指出了它在 DeepSeek 类模型上的两个硬伤缺陷一块大小 256 与 DeepSeek 张量形状不匹配IQ1_S的量化块block大小为 256。作者用于测试的 DeepSeek-Lite 有大量张量的行数row size不能被 256 整除导致这些张量无法用IQ1_S量化只能回退到IQ4_NL4.5 bpw大幅推高模型整体比特数。这正是极低比特量化在巨型 MoE 上不划算的典型原因。缺陷二super-block 的 f16 缩放开销IQ1_S每个 super-block 需要一个f16的缩放因子scale这部分元数据开销让它的实际比特率略高于理论值1.5625 bpw。IQ1_S_R4正是针对这两个问题设计的详见下一节。二、IQ1_S_R4 核心设计1.5 bpw、四行交织、每行 f16 缩放2.1 设计要点一览PR #185 描述中明确给出了IQ1_S_R4的三大设计要点设计维度IQ1_SIQ1_S_R4影响比特率1.5625 bpw1.5 bpw相同模型体积再缩减约 4%缩放因子super-block 级f16scale每行per-rowf16scale去掉 super-block scale 元数据开销块大小25632适配行数不可被 256 整除的张量PR 原文IQ1_S_R4uses 1.5 bpw instead of the 1.5625 bpw needed byIQ1_S. Thef16super-block scale is removed and is replaced by af16scale per rowIQ1_S_R4is implemented with a block size of 32. I wanted to have this because DeepSeek-Lite, the model Im testing with, has a lot of tensors with row sizes not divisible by 256, so a significant fraction of tensors gets quantized toIQ4_NLwhen usingIQ1_S其中块大小 32 的设计尤为关键它让更多张量能够真正落入 1.5 bpw 的量化路径而不是被迫回退到IQ4_NL4.5 bpw或Q5_0。从对话中的量化日志可以清楚看到这一点DeepSeek-R1 的attn_k_b.weight形状[128, 65536]行数 128在IQ1_S_R4模式下依然会被回退到q5_0而如果连 128 行都不满足整除条件回退会更多。2.2 源码中的类型定义IQ1_S_R4并非临时 hack而是仓库中一等公民的 GGML 类型。在 ggml/include/ggml.h 中可以找到GGML_TYPE_IQ1_S_R4 219ggml/include/ggml.hGGML_TYPE_IQ1_M_R4 229ggml/include/ggml.h对应的文件级类型GGML_FTYPE_MOSTLY_IQ1_S_R4 218、GGML_FTYPE_MOSTLY_IQ1_M_R4 223ggml/include/ggml.h在量化工具的类型注册表中IQ1_S_R4的官方描述就是 1.5 bpw quantizationIQ1_M_R4为 1.75 bpw quantizationexamples/quantize/quantize.cpp。也就是说只要使用支持该类型的 quantize 工具IQ1_S_R4就能被识别并启用。2.3 底层 GEMM 实现IQ1_S_R4的矩阵乘法走的是 iqk 风格实现。在 ggml/src/iqk/iqk_gemm_1bit.cpp 中可以看到专门为它注册的乘法函数mul_mat_iq1_s_r4_q8_1IQ1_S_R4×Q8_1激活的矩阵乘法ggml/src/iqk/iqk_gemm_1bit.cppmul_mat_iq1_m_r4_q8_0IQ1_M_R4×Q8_0激活的矩阵乘法ggml/src/iqk/iqk_gemm_1bit.cpp同时 ggml/src/iqk/iqk_quantize.cpp 中为GGML_TYPE_IQ1_S_R4/GGML_TYPE_IQ1_M_R4提供了量化路径ggml/src/iqk/iqk_quantize.cpp量化时也支持行内按块处理QHelper以block_size为单位遍历。从源码结构看IQ1_S_R4在 iqk 框架下同时具备量化与 GEMM 实现这解释了 PR 中CPU 上比 IQ1_S 快得多的结论——IQ1_S一直没有 iqk 风格 GEMM只能跑在主线上蜗牛速度的通用实现。三、MoE 模型的量化混合调整3.1 关于动态量化的澄清PR #185 描述中有一段非常尖锐的行业观察It is funny to observe how much credit Unsloth collected for their DeepSeek-R1 quantization. Their so called dynamic quantization has been inllama.cppsince the introduction of k-quants. The only reason it does not work well for DeepSeeks models is that the attention tensors have different names so that the heuristics used to assign a higher bpw quantization to the attention tensors fails.翻译过来就是所谓的动态量化按张量重要程度分配不同比特率早在 k-quants 时代就内置在 llama.cpp 中Unsloth 方案在 DeepSeek 上表现不佳的真正原因是 DeepSeek 的注意力张量命名与主流模型不同例如attn_v_b.weight、attn_k_b.weight导致原有的给注意力张量更高比特率的启发式规则失效。IQ1_S_R4的量产流程正是围绕修正这套命名规则展开的。3.2 当前仓库的量化混合规则PR 合并进主线后这套规则沉淀在 src/llama-quantize.cpp 中。当目标类型为LLAMA_FTYPE_MOSTLY_IQ1_S_R4或LLAMA_FTYPE_MOSTLY_IQ1_M_R4时src/llama-quantize.cpp按张量名分配量化类型张量名匹配分配类型备注attn_v.weightn_expert4或n_gqa4→IQ4_K_R4n_gqa2→IQ3_K_R4否则Q2_K_R4V 投影对质量敏感给更高比特src/llama-quantize.cppattn_k*n_expert8Q4_K_R4DeepSeek 类 MoE 的 K 投影src/llama-quantize.cppblk.0.ffn_down/gate/upn_expert8IQ3_K_R4首层 FFNsrc/llama-quantize.cppattn_q*n_expert8Q4_K_R4Q 投影src/llama-quantize.cppattn_qkv.weightIQ2_K_R4无 GQA 架构的融合 QKVsrc/llama-quantize.cpp_shexp.weightIQ4_K_R4MoE 共享专家src/llama-quantize.cppffn_down前 1/8 层 →Q2_K_R4其余由--ffn-down-type控制down 投影是 MoE 中最昂贵的张量第一层给更高比特src/llama-quantize.cppattn_output.weightn_expert4→Q5_K_R4否则IQ2_K_R4输出投影src/llama-quantize.cpp这套规则与 PR 对话中 saood06 的观察一致DeepSeek-R1 的专家 FFN 张量ffn_gate_exps.weight/ffn_up_exps.weight会落到iq1_s_r41.5 bpw 的 256 专家部分而ffn_down_exps.weight则默认q2_k_r4——因为 down 投影对量化更敏感详见下文社区反馈一节。四、CPU 实测性能PP 提升 3.65.1 倍4.1 完整性能数据表PR #185 在三种 CPU 平台、两种负载prompt processingpp512与 token generationtg128上对比了IQ1_S与IQ1_S_R4。为避免量化类型差异干扰作者特意选择 LLaMA-3.1-8B 而非 DeepSeek-Lite后者会因行数不可整除导致部分张量回退到其他类型。数据完整转载如下平台线程测试t/s (IQ1_S)t/s (IQ1_S_R4)加速比AVX2 (Ryzen-5975WX)32pp51259.91 ± 0.07218.78 ± 0.143.652Zen4 (Ryzen-7950X)16pp51235.78 ± 0.11183.03 ± 1.095.115NEON (M2-Max CPU)8pp51221.71 ± 0.2478.37 ± 0.003.610AVX22tg1283.46 ± 0.005.05 ± 0.001.460AVX24tg1286.89 ± 0.009.86 ± 0.001.431AVX28tg12813.01 ± 0.0817.54 ± 0.031.348AVX216tg12821.99 ± 0.0128.18 ± 0.001.281AVX232tg12831.66 ± 0.0233.22 ± 0.011.049Zen42tg1284.41 ± 0.016.94 ± 0.011.574Zen44tg1288.41 ± 0.0012.97 ± 0.011.542Zen48tg12814.04 ± 0.0220.31 ± 0.001.447Zen416tg12823.53 ± 0.0229.15 ± 0.021.239NEON2tg1285.12 ± 0.006.86 ± 0.011.340NEON4tg1289.63 ± 0.0013.01 ± 0.011.351NEON8tg12818.26 ± 0.1424.30 ± 0.031.331结论解读Prompt processingPP提升最猛Zen4 上 pp512 从 35.78 t/s 跳到 183.03 t/s加速 5.1 倍AVX2 与 NEON 也分别达到 3.65 倍和 3.61 倍。原因正如 PR 所述IQ1_S从未实现 iqk 风格 GEMM只能跑主线的慢速实现而IQ1_S_R4有专门的 iqk 内核ggml/src/iqk/iqk_gemm_1bit.cpp。Token generationTG提升约 1.31.6 倍小线程数下2-4 线程提升更明显随线程数增加加速比收敛32 线程时仅 1.05 倍符合 TG 受内存带宽约束的规律。同一行号左侧空白表示与上一行相同平台。4.2 质量评估PPL-512 对比PR 还给出了极低比特下的困惑度perplexity对比todays mainlinellama.cpparrives at a context-512 perplexity (PPL(512)) of 36.8 for DeepSeek-Lite using 2.62 bpw. TheIQ1_S_R4quantization in this PR getsPPL-512 9.4with 1.766 bpw for the repeating layers.即在更低的平均比特率1.766 bpw vs 2.62 bpw下IQ1_S_R4的 DeepSeek-Lite PPL-512 从 36.8 大幅下降到 9.4。这是更低比特 更好质量的组合核心来源正是行数不可整除问题的解决与量化混合规则的修正。五、实战把 DeepSeek-R1 量化为 IQ1_S_R45.1 基本命令使用仓库自带的 quantize 工具examples/quantize/quantize.cpp基本形式./build/bin/quantize \ opensourcerelease_DeepSeek-R1-Bf16-256x21B-F16.gguf \ opensourcerelease_DeepSeek-R1-Bf16-256x21B-IQ1_S_R4.gguf \ IQ1_S_R4 48参数说明第一个参数源模型 GGUFf16/bf16 版本第二个参数输出文件路径IQ1_S_R4目标量化类型类型名不区分大小写工具内部会转大写匹配见 examples/quantize/quantize.cpp48线程数PR 对话中实测使用的值。5.2 必须覆盖的默认值token 嵌入层重要坑点PR 作者明确提醒IQ1_S_R4默认把token_embd.weight量化为Q2_K这一默认值在当前仓库源码中仍然存在见 src/llama-quantize.cpp但Q2_K的 token 嵌入在 DeepSeek-Lite 上表现不佳。作者的做法是手动覆盖./build/bin/quantize \ model-f16.gguf model-IQ1_S_R4.gguf \ IQ1_S_R4 48 \ --token-embedding-type q8_0--token-embedding-type参数在工具帮助中定义为使用指定的 ggml_type 处理token_embd.weight张量examples/quantize/quantize.cpp。Q8_0的嵌入层虽然略增体积但对 DeepSeek 的极低比特体验有明显帮助。5.3 关于 imatrix重要性矩阵PR 对话中的实测日志显示社区用户使用 imatrix 辅助量化load_imatrix: imatrix datasetimatrix-training-full-3 load_imatrix: loaded 720 importance matrix entries from .../imatrix.dat computed on 315 chunksimatrix 的作用是按激活幅度为不同权重赋予不同的量化优先级配合 imatrix 生成工具 使用。量化时通过--imatrix指定.dat文件即可。注意极低比特量化1.5-2 bpw对 imatrix 质量更敏感建议使用与目标任务分布接近的数据集。六、量化日志解读如何验证该高比特的张量确实拿到了高比特PR 对话中 saood06 提供了完整的 DeepSeek-R1 量化日志这是理解IQ1_S_R4实际落地效果的最好素材。关键片段main: quantizing .../opensourcerelease_DeepSeek-R1-Bf16-256x21B-F16.gguf to .../opensourcerelease_DeepSeek-R1-Bf16-256x21B-IQ1_S_R4.gguf as IQ1_S_R4 using 48 threads llama_model_loader: loaded meta data with 48 key-value pairs and 1147 tensors ... [ 18/1147] blk.1.ffn_gate.weight - [7168, 18432, 1, 1], typef16, converting to iq1_s_r4 .. 252.00 MiB - 23.66 MiB [ 59/1147] blk.3.ffn_down_exps.weight - [2048, 7168, 256, 1], typef16, converting to q2_k_r4 .. 7168.00 MiB - 1176.00 MiB [ 60/1147] blk.3.ffn_gate_exps.weight - [7168, 2048, 256, 1], typef16, converting to iq1_s_r4 .. 7168.00 MiB - 673.00 MiB [ 61/1147] blk.3.ffn_up_exps.weight - [7168, 2048, 256, 1], typef16, converting to iq1_s_r4 .. 7168.00 MiB - 673.00 MiB [ 166/1147] blk.9.attn_k_b.weight - [128, 65536, 1, 1], typef16, llama_tensor_get_type : tensor cols 128 x 65536 are not divisible by 256, required for q4_k_r4 - using fallback quantization q5_0 converting to q5_0 .. size 16.00 MiB - 5.50 MiB日志中有四个值得注意的信号专家张量的类型分配符合预期ffn_down_exps→q2_k_r4down 投影给更高比特ffn_gate_exps/ffn_up_exps→iq1_s_r41.5 bpw与 src/llama-quantize.cpp 的规则一一对应。attn_k_b.weight因 256 整除问题回退到q5_0即使块大小降为 32DeepSeek-R1 的attn_k_b128 行仍不满足q4_k_r4需要的 256 整除回退到了q5_0。这提醒我们IQ1_S_R4解决了大部分张量的整除问题但个别张量仍会回退日志里出现q5_0/Q8_0属于正常现象。缩放系数直观可查每行张量前的size X MiB - Y MiB可以快速估算实际压缩率例如7168 MiB - 673 MiB的专家 gate/up 张量约压缩 10.6 倍接近 1.5 bpw 的理论值。整体结果日志尾部显示model size 1282038.27 MBquant size 367657.12 MB约 367 GB 总量注意这是完整 256×21B 版本在混合规则下的结果量化耗时约 2.86 小时10290932.85 ms。6.1 社区补丁为attn_v_b.weight修正命名匹配saood06 在对话中还贴出了一个针对当时源码的关键补丁让attn_v_b.weightDeepSeek MLA 架构的 V 投影带_b后缀也能命中高比特分支--- a/src/llama.cpp b/src/llama.cpp -16215,7 16215,7 static ggml_type llama_tensor_get_type(...) } else if (ftype LLAMA_FTYPE_MOSTLY_IQ1_S_R4) { - if (name.find(attn_v.weight) ! std::string::npos) { if (name.find(attn_v.weight) ! std::string::npos || name.find(attn_v_b.weight) ! std::string::npos) { if (qs.model.hparams.n_expert 4 || qs.model.hparams.n_gqa() 4) new_type GGML_TYPE_IQ4_K_R4; else if (qs.model.hparams.n_gqa() 2) new_type GGML_TYPE_IQ3_K_R4; else new_type GGML_TYPE_Q2_K_R4;这一命名问题正是 PR 描述中DeepSeek 注意力张量命名不同导致启发式规则失效的活例子。在后续合入的版本中这类 MLA 张量的处理已随架构支持完善当前仓库对 MLA 的attn_v_b类张量走 llama-dsv4.cpp 等架构专用路径但理解这一 patch 的动机有助于你排查自己的极低比特量化日志。七、社区反馈与已知边界7.1 尺寸差异的来源saood06 实测自己用该 PR 量化 DeepSeek-R1 得到约 127 GB 的结果比 Unsloth 的版本小。作者解释It ends up being smaller than Unsloths becauseIQ1_S_R4is 1.5 bpw vs 1.5625 bpw forIQ1_S. This 4% difference pretty much corresponds to the difference between 131 GiB and 127 GiB.即 127 GiB vs 131 GiB 的差距约 3%基本完全来自 1.5 bpw vs 1.5625 bpw 的 4% 比特率差异——这是设计层面实打实省下来的体积。7.2 极低比特的能不能用之争saood06 的实测反馈也相当坦诚Sadly, it doesnt really function. I havent tried his IQ1_S, but yours might just be too small. You did a 127 GB. The unsloth creator said on reddit I had a 127GB version, but it didnt go that good.这说明1.5 bpw 的 127 GB 版本在 DeepSeek-R1 上可能质量不足以实用。作者回复表示希望看到量化日志以验证高比特张量是否正确选中。这是极低比特量化的真实边界PPL 数字好看9.4 vs 36.8与推理质量可实用之间仍有距离。7.3 已知的张量敏感性jukofyork 在对话中补充了两条对 DeepSeek-R1 极低比特量化的关键经验attn_k_b.weight不能保留为 f16会导致模型在输出thinking标签后不断重复同一句话建议量化为Q8_0等有损但无截断的类型。ffn_down_exps.weight的比特率极其敏感降到Q3_K及以下模型会明显变笨——思考长度缩短、不复用输入的引用文本、规划能力退化。这与量化规则中down 投影给更高比特q2_k_r4即 2 比特起步的设计相互印证。作者对此补充了技术解释在主线上模型张量为 f16 时激活会先被转成 f16 再乘若激活超出 f16 范围就会被截断导致模型变笨而在本仓库 x86_64 上实现了任意fpX × fpY组合的 GEMMf16 模型张量可以直接与 f32 激活相乘不存在截断问题ggml/src/iqk/iqk_gemm_1bit.cpp 中即包含多种 fp 组合的乘法内核。ARM 平台出于速度考虑仍会转 f16 激活M2-Max 上 fp16×fp16 几乎快 2 倍。7.4 平台支持范围PR #185 合并时IQ1_S_R4仅支持 CPU描述原文Caveat: it is CPU only for now.。不过在后续版本中CUDA 支持已经合入README 明确记录IQ1_S_R4与IQ1_M_R4的 CUDA 实现分别来自 PR #492 与 PR #494README.md仓库中也能找到对应的 CUDA 模板实例例如 ggml/src/ggml-cuda/template-instances/mmq-instance-iq1_s_r4.cu 与 mmvq-instance-iq1_m_r4.cu。如果你需要在 GPU 上运行IQ1_S_R4模型请使用包含上述 PR 的较新版本并留意各自的适用条件。八、总结与源码索引IQ1_S_R4是 ik_llama.cpp 在极低比特量化方向上的代表性产出设计层面用每行 f16 scale 替代 super-block f16 scale1.5625 → 1.5 bpw块大小从 256 降到 32解决 DeepSeek 系张量整除问题质量层面修正 MoE 注意力/FFN 张量的命名匹配与混合比特分配DeepSeek-Lite 上 PPL-512 从 36.82.62 bpw降到 9.41.766 bpw性能层面CPU 上 PP 提速 3.65.1 倍、TG 提速 1.31.6 倍相对IQ1_S的慢速通用实现边界层面PR 合并时仅 CPUDeepSeek-R1 在 1.5 bpw 下的实用性仍需谨慎评估attn_k_b与ffn_down_exps是需要额外关注的敏感张量。如需深入阅读推荐以下仓库内路径量化类型注册与描述examples/quantize/quantize.cppGGML 类型常量ggml/include/ggml.hIQ1_S_R4/IQ1_M_R4 量化混合规则src/llama-quantize.cppiqk GEMM 内核ggml/src/iqk/iqk_gemm_1bit.cppiqk 量化实现ggml/src/iqk/iqk_quantize.cpp后续 CUDA 支持与更多 R4 量化类型说明README.md【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考