BF16 Trellis 量化加速:ik_llama.cpp 的 IQ2_KT / IQ3_KT / IQ4_KT CPU 推理优化解析
BF16 Trellis 量化加速ik_llama.cpp 的 IQ2_KT / IQ3_KT / IQ4_KT CPU 推理优化解析【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cppBF16bfloat16精度在 CPU 推理中的价值通过 ik_llama.cpp 的 PR #484 得到了直观展示该 PR 为 trellis 量化格式IQ2_KT、IQ3_KT、IQ4_KT增加了基于原生bf16指令的 CPU 实现在支持 bfloat16 的 CPU如 AMD Ryzen 7950X上prompt processing 吞吐提升接近翻倍token generation 也有 5%-10% 的提升。本文以该 PR 为核心结合当前仓库的源码实现梳理 trellis 量化的背景、BF16 优化的原理、实测收益、已知局限以及当前仓库中该特性的最终落地形态。背景trellis 量化与 CPU 推理瓶颈Trellis 量化IQ1_KT、IQ2_KT、IQ3_KT、IQ4_KT是 ik_llama.cpp 项目在量化方向的标志性特性之一。根据项目 README.md 的介绍这类量化最初由 CUDA 实现PR 113后续陆续补齐了 MetalPR 475、NEONPR 471、CPUPR 441等后端并基于一种新颖的整数基 trellisinteger-base trellis设计使得在 CPU 上也能获得合理的推理性能。Trellis 量化之所以特殊在于它的反量化dequantization不是简单的查表或缩放而是需要通过trellis 状态机逐元素生成权重值。以 iqk_gemm_ktquants.cpp 中的核心函数为例inline uint32_t trellis_next(uint32_t val) { constexpr uint32_t ka 89226354; constexpr uint32_t kb 64248484; constexpr uint32_t kmask 0x8fff8fff; constexpr uint32_t km32 0x3b603b60; val val*ka kb; return (val kmask) ^ km32; } inline float trellis_gen(uint32_t val, uint32_t* s) { const ggml_fp16_t * h (const ggml_fp16_t *)s; s[0] trellis_next(val); return GGML_FP16_TO_FP32(h[0]) GGML_FP16_TO_FP32(h[1]); }每次生成权重都要经过 32 位整数乘法LGC 线性同余生成器、掩码与异或再从 fp16 字面量转换为 fp32 求和。这种逐元素生成 转换的开销正是 trellis 量化在 CPU 上 prompt processingPP速度明显落后于 row-interleaved 量化如IQ2_K_R4等的根本原因——PR #484 的描述中明确对比在 Ryzen-7950X 上trellis 量化的 PP-512 只有 126-132 t/s而 row-interleaved 量化可达 240-300 t/s。PR #484 的核心内容BF16 CPU 实现PR #484github-data/pull_requests/484 - BF16 Trellis implementation.md的核心目标就是为IQ2_KT、IQ3_KT、IQ4_KT三种 trellis 量化类型在支持原生 bf16 的 CPU上提供专门的实现路径。bf16 拥有与 fp32 相同的 8 位指数位因此动态范围与 fp32 相当且支持点积指令如 x86 的_mm512_dpbf16_ps可以在单条指令内完成多组 bf16 乘加——这正是加速矩阵乘法mul_mat的关键。性能收益官方实测数据PR #484 的作者 ikawrakow 在 Ryzen-7950X原生支持 bf16上以 8B LLaMA-3 为基准给出了两组实测数据这些数据是本文档的核心证据完整引用如下。TG-128token generation批大小 128类型f32 t/sbf16 t/sIQ2_KT12.1712.65IQ3_KT10.5411.22IQ4_KT8.399.45PP-512prompt processing512 token 前缀类型f32 t/sbf16 t/sIQ2_KT132.47233.96IQ3_KT127.80233.37IQ4_KT126.31243.17从数据可以清晰看出PP 收益远大于 TG 收益PP-512 从约 127-132 t/s 提升到约 233-243 t/s接近翻倍而 TG-128 仅提升约 5%-10%如 IQ4_KT 从 8.39 提升到 9.45 t/s。这与优化性质一致——PP 阶段是 compute-bound 的矩阵乘法主导bf16 点积指令的吞吐优势能充分发挥而 TG 阶段受限于内存带宽与单 token 依赖提升有限。bf16 后的 trellis 量化已与 row-interleaved 量化可比PP-512 达到 230-240 t/s 区间后与作者在 Ryzen-7950X 上测得的 row-interleaved 量化240-300 t/s基本处于同一水平trellis 量化在 CPU 上的最大短板PP 慢被补齐。为什么是 bf16 而不是 f32在 PR #484 之前trellis 量化的 CPU 内核以 f32 累积路径为主。BF16 实现的核心差异在于指令级吞吐翻倍bf16 是 16 位类型在同样的 SIMD 寄存器宽度下一次可装载的权重数量是 fp32 的两倍配合_mm512_dpbf16_psAVX512-BF16 点积指令可以在一轮指令内完成多组 bf16×bf16 乘加并累加到 fp32 累加器。动态范围与 fp32 相同bf16 保留 8 位指数避免了 fp16 在小尾数下易出现的上下溢问题更安全地用于权重反量化路径。消除转换开销反量化过程中权重可以从 bf16 直接参与点积无需先展开成 fp32。PR #484 的讨论中还提到一个重要的数值稳定性经验作者在 NEON 上实现 fp16 版本时曾遇到 NaN被迫仔细处理上下溢并区分哪些步骤必须用 fp32 计算而在 bf16 版本中类似问题相对较少但仍需警惕。这说明用低精度类型加速的前提是精确控制数值路径不能无脑替换。源码级落地从 PR 到当前仓库PR #484 最终在 2025-06-19 被关闭Closing in favor of #529其思路并未废弃而是被后续 PR #529New IQ2_KT, IQ3_KT and IQ4_KT V2继承演进。当前仓库中BF16 相关的 CPU 加速逻辑已经沉淀在 IQKik 量化内核子系统中。IQK 内核子系统与 bf16 矩阵乘法当前仓库的 CPU 矩阵乘法实现位于 ggml/src/iqk/ 目录其中 iqk_gemm_floats.cpp 明确注释了该文件处理 f16、bf16当原生 bf16 可用时与 f32 矩阵且结果累积到 f32见 iqk_gemm_floats.cpp。核心实现大量使用_mm512_dpbf16_ps指令例如acc[2*iy0] _mm512_dpbf16_ps(acc[2*iy0], qx[0], (__m512bh)_mm512_shuffle_epi32(y, _MM_PERM_ENUM(0x00)));这段代码展示了典型的 bf16 点积模式从 bf16 权重块中取出经过 shuffle 的 16 位数据直接与激活的 bf16 值做乘加累加器保持 fp32 精度。BF16 内核的注册逻辑集中在 iqk_gemm_floats.cppset_mul_mat_bf16、set_mul_mat_bf16x8、set_mul_mat_bf16_r16等函数根据矩阵布局标准行布局或 R16 重打包布局选择对应的内核函数其中mul_mat_bf16_r16_bf16等函数会直接处理 bf16 输入并输出 bf16 结果。值得注意的是当前仓库中的 bf16 能力已不止服务于 trellis 量化还包括bf16 激活的矩阵乘法iqk_gemm_floats.cpp中按GGML_TYPE_BF16匹配的内核见 iqk_gemm_floats.cpp可用于 bf16 权重或激活的通用乘加路径。bf16 K-cache 闪存注意力FA在 ggml/src/iqk/fa/ 下多个 FA 内核文件中__AVX512BF16__编译分支支持 bf16 类型的 K/V cache 参与 flash attention通过_mm512_dpbf16_ps计算 QK 点积见 iqk_fa_templates.h并明确指出 bf16 K-cache 不与其它类型混用见 iqk_fa_64_64.cpp。bf16 行重打包repack量化/反量化路径中支持将 f32/f16 数据重打包为GGML_TYPE_BF16_R16布局以配合 r16 系列内核见 iqk_quantize.cpp 与 iqk_quantize.h。编译与启用方式BF16 路径依赖编译器与 CPU 的双重支持当前仓库通过 CMake 控制GGML_IQK_MUL_MAT开启 IQK 矩阵乘法内核并定义GGML_USE_IQK_MULMAT见 ggml/src/CMakeLists.txt这是 trellis/legacy quants 相关 CPU 内核的总开关。在 AVX512 编译选项中GGML_AVX512_BF16会为 C/C 编译单元追加__AVX512BF16__宏定义见 ggml/src/CMakeLists.txt这是触发 bf16 专用代码路径如_mm512_dpbf16_ps的编译期条件。PR #484 的讨论中还给出了一个针对 CUDA 后端的实用提示若在 GPU 上遇到低 TG 性能需要显式启用 CUDA 的 F16 路径即cmake -DGGML_CUDA_F16ON。这一提示的背景是 bf16 内核在 CPU 上加速后GPU 与 CPU 的吞吐差距可能被放大GPU 侧需要对应开启更高效的半精度路径才能匹配。一个典型的构建命令示例x86-64 CPU启用 IQK 矩阵乘法与 AVX512-BF16cmake -B build -DGGML_IQK_MUL_MATON -DGGML_AVX512ON -DGGML_AVX512_BF16ON cmake --build build --config Release -j注意-DGGML_AVX512_BF16ON仅应在确认 CPU 支持 AVX512-BF16 指令集时开启否则二进制在旧 CPU 上会触发非法指令。对于 Ryzen 7950X 这类 Zen4 架构 CPU原生支持 AVX512-BF16。已知局限与数值稳定性问题PR #484 的对话记录是理解该优化边界的第一手资料包含两个值得注意的问题1. 低 GPU TG 性能与 CUDA F16 开关作者在回复测试者时指出GPU 侧 TG 性能偏低时很可能需要在 CUDA 构建中显式启用 F16cmake -DGGML_CUDA_F16ON否则 CUDA 后端不会使用半精度路径与 CPU 侧的 bf16 加速形成落差。2. DeepSeek 模型在 bf16 精度下失效作者在 2025-06-03 的测试中发现DeepSeek-Lite 在 bf16 精度下虽然不产生 NaN但 perplexity 极高、生成内容为乱码gibberish。这说明 bf16 路径并非对所有模型都安全——部分模型如 DeepSeek 系列对低精度权重表示的容忍度更低。这一发现也是后续 PR #529 对 KT 量化格式进行 V2 重构、并最终取代 PR #484 的重要动因。结合作者在 NEON fp16 实现中遇到的 NaN 经验必须小心上下溢、部分步骤须用 fp32 计算可以总结出这类低精度加速的通用约束数值路径中的关键中间量如缩放因子、残差必须保持 fp32低精度类型只能用于加载→乘加→累加这一吞吐敏感环节不同模型架构对低精度的敏感度差异很大启用前应实测 perplexity 与生成质量。演进脉络PR #484 的继承与后续发展PR #484 于 2025-06-19 关闭作者明确说明Closing in favor of #529。从当前仓库 README 与 PR 列表可以梳理出 trellis 量化 CPU 加速的完整演进链PR 113原始 CUDA 实现trellis 量化起点PR 441 / PR 471 / PR 475分别补齐 CPU、NEON、Metal 后端PR 453 / PR 482IQ3_KT / IQ4_KT 提速与 CPU prompt processing 优化PR 484本文主角BF16 CPU 实现PP 翻倍、TG 5%-10%PR 529全新的 IQ2_KT / IQ3_KT / IQ4_KT V2整数基 trellis在保留 CPU 性能的同时重构量化格式最终取代 PR #484PR 616新增 IQ1_KT1.75 bpw。README 中明确指出当前仓库的 trellis 量化基于新颖的整数基 trellis设计见 README.md这正是一系列 CPU 性能优化包括 BF16 内核的最终形态。也就是说PR #484 的 bf16 加速思想并未消失而是被吸收进 IQK 子系统的通用 bf16 矩阵乘与 FA 内核中继续为 trellis 及更多量化类型服务。总结PR #484 用一组干净利落的实测数据证明了 bf16 在 CPU 推理中的价值在支持原生 bf16 的 x86 CPU如 Ryzen-7950X上trellis 量化IQ2_KT/IQ3_KT/IQ4_KT的 prompt processing 吞吐从约 127-132 t/s 跃升至约 233-243 t/s接近翻倍token generation 也获得 5%-10% 的增益使得 trellis 量化在 CPU 上的整体表现与 row-interleaved 量化基本拉平。虽然该 PR 因后续 V2 重构PR #529而被关闭但其 bf16 内核思想已沉淀为当前仓库 IQK 子系统的通用能力bf16 矩阵乘法、bf16 K-cache flash attention、bf16 R16 重打包并通过GGML_IQK_MUL_MAT与GGML_AVX512_BF16两个 CMake 开关控制。对于希望榨干现代 CPUZen4推理性能的开发者理解这条 bf16 优化路径是使用 trellis 量化在 CPU 上获得接近 GPU 体验的关键前提同时也应记住 PR 中记录的经验教训低精度加速必须配合 perplexity 验证且不同模型如 DeepSeek 系列对 bf16 的兼容性存在差异。【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →