FP8 原生模型支持探索:ik_llama.cpp 中 FP8 GGUF 创建与再量化方案复盘(PR 454)
2026/9/20 6:04:33 网站建设 项目流程
  • 人工智能
  • 大模型
  • 推理引擎
  • 本地部署
  • 模型量化
  • 模型优化

【免费下载链接】ik_llama.cpp

llama.cpp fork with additional SOTA quants and improved performance

项目地址:https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp
点击查看免费下载

导读

随着 DeepSeek、Qwen 等厂商开始直接发布 FP8(E4M3)格式的原生权重,推理引擎面临一个新问题:如何不经过 BF16/FP16 中间环节,直接读取并处理 FP8 原生模型。本文以 ik_llama.cpp 仓库中编号 454 的 PR(Add support for FP8 GGUF creation and re-quantization,WIP)为核心,复盘该 PR 的目标、实现思路(weight_scale_inv与 FP8_E4M3 量化方法)、关键设计讨论(FP8 矩阵乘法的两种实现路径),并结合当前仓库中的转换脚本与量化工具源码进行佐证。读完本文,你将理解 FP8 原生模型进入 GGUF 生态所需的技术拼图,以及该 PR 最终被关闭的原因与后续启示。

一、背景:FP8 原生模型与 E4M3 格式

FP8 是 8 位浮点格式,常见两种变体:

  • E4M3:4 位指数 + 3 位尾数,精度较高,是权重存储的主流选择;
  • E5M2:5 位指数 + 2 位尾数,动态范围更大,常用于激活值。

PR #454 的目标明确限定在E4M3:直接处理 FP8(E4M3)原生模型——先创建一个 FP8 GGUF,再进一步量化成可用于推理的 GGUF。PR 作者saood06明确指出,对 FP8 权重直接推理不在该 PR 范围内(类似于 #169 的做法)。

该 PR 最初用 Qwen/Qwen3-0.6B-FP8 这个微型模型验证:成功创建 GGUF 并能够 dump。作者选择该模型的理由是它「与 DeepSeek 使用相同的 scale 方式」且体积小。而 RedHatAI/Mistral-Nemo-Instruct-2407-FP8 这类模型对 scale 的处理方式不同,作者认为若要支持所有 FP8 原生模型,这一点必须在后续解决。

注:本 PR 为 WIP 草稿,创建于 2025-05-24,最终于 2025-06-15 因实现代码错误被作者主动关闭(Closed)。

二、PR 目标:一条「FP8 GGUF → 再量化」的管线

该 PR 提出的管线分两步:

  1. 创建 FP8 GGUF:把 HF 上以 FP8(E4M3)原生存储的权重直接打包为 GGUF,保留其 FP8 表示,而不是先反量化到 FP16/BF16 再存储;
  2. 再量化:把 FP8 GGUF 作为中间产物,量化为可供推理引擎直接加载的常规量化格式(如 Q8_0 或各 IQ 系量化)。

从当前仓库源码可以确认这条管线的可行性基础:

  • convert_hf_to_gguf.py 中LazyTorchTensor._dtype_str_map已经映射了"F8_E4M3": torch.float8_e4m3fn"F8_E5M2": torch.float8_e5m2,说明转换脚本具备识别 safetensors 中 FP8 dtype 的能力;
  • examples/quantize/quantize.cpp 是仓库内完成「再量化」环节的成熟工具(llama-quantize),其量化类型表中包含 Q8_0、Q6_0、MXFP4、IQ4_XS 等一系列目标格式。

也就是说,PR #454 所设想的「创建 FP8 GGUF + 再量化」两步,在仓库现有工具链中分别对应转换脚本(识别 FP8 输入)与量化工具(产出推理格式)两大环节。

三、实现细节:weight_scale_inv 与 FP8_E4M3

PR 目前只实现了第一步(FP8 GGUF 创建),涉及两个关键组成部分:

  • weight_scale_inv:FP8 原生模型(尤其 DeepSeek 系)通常为按块存储的逆缩放因子张量,用于把 FP8 整数位型还原为真实浮点值。该 PR 需要把这一张量一并纳入 GGUF 的张量集合并正确映射;
  • FP8_E4M3 量化方法:在 GGUF 类型体系中新增一个表示 FP8 E4M3 的量化类型入口。

作者在 PR 中特别说明:FP8_E4M3的枚举值暂时设为 999,因为作者不确定它应该插入到枚举的哪个位置。这一细节侧面反映了给 GGUF 新增一种存储类型的「命名与编号」成本。

作为参照,当前仓库中 GGUF/ggml 的类型体系可以印证这一点:

  • gguf-py/gguf/constants.py 中的GGMLQuantizationType枚举按编号管理(如F16 = 1BF16 = 30);
  • ggml/include/ggml.h 中ggml_type枚举同样按编号排列(GGML_TYPE_F16 = 1GGML_TYPE_Q8_0 = 8GGML_TYPE_BF16 = 30),并已扩展到 200+ 号段的 R 系列变体。

可见在枚举中插入新类型会影响 GGUF 文件头解析、块大小表(GGML_QUANT_SIZES)与量化工具的类型表等多处代码,这也是 PR 作者以 999 占位、等待上游确认槽位的原因。

四、关键设计讨论:FP8 矩阵乘法的两条实现路径

PR 讨论区中,项目作者 ikawrakow 在 2025-05-25 提出了 FP8 权重矩阵乘法实现的核心设计问题,这是整个讨论中最具技术价值的部分:

路径 A:先乘 scale 再做 FP8 乘加

在乘以 FP8 张量之前,需要先用 fp8 的 scale 去乘激活值。

即把weight_scale_inv从权重侧转移到激活侧,让 FP8 的块级缩放体现在激活上,之后直接做 FP8 位型之间的乘加。PR 作者表示这正是他打算采用的方案:「这是对我来说最有意义的做法,即便另一种方案可能更好」。

路径 B:直接转换为 Q8_0,把 scale 折进 Q8_0 的量

另一种选择是直接把 FP8 张量转换为 Q8_0,把 scale 折叠进 Q8_0 的量中。

Q8_0 在 ggml 中是 32 元素一块、带一个 fp16 scale 的经典量化类型(见 ggml/include/ggml.h 与 gguf-py/gguf/constants.py 中GGML_QUANT_SIZES对 Q8_0 的(32, 34)定义)。由于 FP8 E4M3 只有 3 位尾数,其数值集合有限,完全可以无损映射到 8 位整数再配以合适的 scale 表达,从而复用 ggml 中成熟的 Q8_0 内核,无需为 FP8 编写新的 CPU 内核。

作者最终仍然选择了路径 A(先乘 scale 再做 FP8 乘加),但该 PR 后续因实现代码本身存在错误而被关闭,两条路径的取舍最终未在该 PR 内收敛为可合并代码。

五、衍生讨论:FP4 与 IQ4 的等价性

PR 关闭前夕(2025-06-15),社区成员whatever1983带来了 NVIDIA 官方 FP4 版 DeepSeek-V3-0324 的消息,并据此提出「FP8 还没做完就已被 FP4 淘汰」的观点。ikawrakow 的回应澄清了一个关键技术事实:

FP4 转成其他 4 位表示(如 IQ4_K、IQ4_XS)是绝对无损的。只需要使用一张与 NVIDIA 的 16 个不同 fp4 值匹配的替代查找表,你就得到了 fp4 实现……4 位就是 4 位,可以直接使用,无需等待 Zen6 或 AMX-FP4,也无需 Chitu 内核,只需很小的改动即可工作。

这与仓库中 IQ4 系量化(如 examples/quantize/quantize.cpp 中的IQ4_XSIQ4_NLIQ4_KT等)的设计理念一致:IQ4 系列本身就基于 16 值查找表,恰好能容纳 FP4 的 16 个离散值,因此从 FP4 原生模型到 IQ4 是「表示级无损」的搬运,而不是有损再量化。

ikawrakow 还补充了两个观点:其一,从 FP4 模型出发做 2/3 位量化,质量可能高于从 FP8/BF16 出发的同类量化;其二,NVIDIA 该 FP4 模型约 420GB,更接近 5 bpw 而非 4 bpw,原因可能是部分张量不是 FP4,或采用了 block=8 + fp8 scale 的方案。这些讨论为后续 FP4/IQ4 工作提供了方向,但与 FP8 无关的细节此处不再展开。

六、PR 结局与复盘

2025-06-15,作者saood06主动关闭了该 PR,理由非常直白:

关闭它,因为尽管这个方案理论上可行,但我的实现是错的……这是一个代码有误的 PR,除了作为实现思路的参考外,几乎没有在其基础上继续开发的价值。

作者同时回应了对 NVIDIA FP4 量化「有推理增益」的猜测:基准数字存在误差区间与测试方法差异,且没有任何证据表明 NVIDIA 做了量化感知训练或量化后微调;DeepSeek 的约 425GB FP4 量化表现与未量化版本大致相当,并不算惊艳——仓库讨论区 #477 中展示的曲线在约 370GB 规模就已接近零损失。至于成本与功耗之争,作者也指出讨论已偏离 PR 本身的技术主题。

七、给后续实现者的启示

综合 PR 正文、讨论与当前仓库源码,可以提炼出几条可复用的结论:

  1. FP8 GGUF 创建是可行的第一步:转换脚本 convert_hf_to_gguf.py 已具备读取 F8_E4M3 dtype 的能力,weight_scale_inv的映射是打通「FP8 原生权重 → FP8 GGUF」的关键;
  2. FP8 推理矩阵乘法有两条清晰路线:先乘 scale 再 FP8 乘加,或折叠 scale 为 Q8_0 复用现有内核。后者实现成本更低,但前者更能保留 FP8 原生计算路径,为未来支持 FP8 硬件加速留出空间;
  3. GGUF 新增类型存在系统性成本:从类型枚举编号(参考 ggml/include/ggml.h 与 gguf-py/gguf/constants.py)到量化类型表(参考 examples/quantize/quantize.cpp 起的类型列表)都需同步扩展,枚举编号占位(如 999)只是临时手段;
  4. FP4 与 IQ4 表示级等价:FP4 的 16 个离散值可无损映射到 IQ4 查找表,这条路径为未来处理 FP4 原生模型提供了比 FP8 更直接的思路。

该 PR 虽已关闭,但其提出的「FP8 GGUF 创建 + 再量化」管线框架、weight_scale_inv处理思路以及关于 FP8/FP4 矩阵乘法的设计讨论,仍可作为在 ik_llama.cpp 中接入 FP8/FP4 原生模型的重要参考。

  • 人工智能
  • 大模型
  • 推理引擎
  • 本地部署
  • 模型量化
  • 模型优化

【免费下载链接】ik_llama.cpp

llama.cpp fork with additional SOTA quants and improved performance

项目地址:https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp
点击查看免费下载

相关推荐

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

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

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

立即咨询