十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ik_llama.cpp 支持 bf16 KV Cache:跨平台精度、性能与实现解析

ik_llama.cpp 支持 bf16 KV Cache:跨平台精度、性能与实现解析 人工智能大模型推理引擎本地部署模型量化模型优化【免费下载链接】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 #69「Allow bf16 kv-cache」展开介绍该 fork 如何将 bfloat16bf16引入 KV Cache 存储类型并分析作者在 CPU 与 CUDA 两个平台上的精度实测结论。读完本文你将理解 bf16 与 fp16 在 KV Cache 场景下的差异、如何在命令行通过--cache-type-k/--cache-type-v启用 bf16 KV Cache以及该特性在底层代码中的校验与数据转换路径从而在自己的推理环境中做出更合理的 KV Cache 位宽选择。一、背景为什么 KV Cache 的存储类型值得关注在 Transformer 架构的自回归解码中每一层注意力都会反复使用先前 token 产生的 Key 与 Value 张量。为避免重复计算推理引擎会把它们缓存起来这就是 KV Cache。KV Cache 的规模随上下文长度和层数线性增长是长上下文推理时显存VRAM或内存RAM占用的大头。KV Cache 的存储类型位宽直接影响两件事内存/显存占用位宽越低每个元素占用的字节越少能容纳的上下文越长输出质量位宽越低量化误差越大模型困惑度PPL越容易劣化。在 ik_llama.cpp 中K 缓存与 V 缓存的类型可以分开指定。该特性最初的版本形态正是 PR #69它把bf16bfloat16加入了合法的 KV Cache 存储类型列表使所有该仓库支持的平台都能以 bf16 运行 KV Cache。二、PR #69 的核心内容与作者实测结论PR #69「Allow bf16 kv-cache」由作者 ikawrakow 于 2024-09-29 提交。其描述非常精炼包含了两个关键实测事实CPU 上精度无损在 CPU 上无论是否启用 Flash AttentionFA使用 bf16 作为 KV Cache 类型得到的困惑度PPL与更高位宽完全一致CUDA 上存在转换缺口在 CUDA 上bf16 KV Cache 的结果约等于 CPU 上 fp16 KV Cache 的结果说明当时 CUDA 路径“缺少了某个转换步骤”作者原文so Im missing some conversion somewhere。尽管存在上述 CUDA 转换缺口PR #69 的目标是让所有该仓库支持的平台都能以 bf16 运行 KV Cache这一点最终达成。换言之这是一个「先让功能在所有平台可用、再逐步打磨 CUDA 精度」的渐进式提交。值得说明的是PR #69 的定位是开启能力本身文档中并未给出具体的 PPL 数值、加速比或显存节省数据因此本文不虚构任何性能数字仅呈现作者给出的定性结论。三、bf16 与 fp16同为 16 位取舍不同bf16 与 fp16 都是 16 位浮点但布局不同特性fp16半精度bf16bfloat16指数位5 位8 位尾数位10 位7 位数值范围与 fp16 一致较小与 fp32 相同精度尾数更精细指数范围大尾数更粗典型用途存储、计算折中AI 训练/推理中的主流低精度格式关键点在于bf16 的指数位与 fp32 完全一致因此它的数值范围与 fp32 相同只是在尾数上更粗糙。对于 KV Cache 这类关注数值分布范围、且后续计算会重新引入精度的场景bf16 往往比同位数 fp16 更“抗溢出”这就是作者在 CPU 上观察到 bf16 与更高位宽 PPL 一致的原因之一。四、如何在命令行启用 bf16 KV Cache在 ik_llama.cpp 中KV Cache 类型通过--cache-type-k与--cache-type-v两个参数分别控制短选项-ctk/-ctv它们接受f32、f16、bf16以及多种量化类型如q8_0作为取值。以 bf16 为例# K、V 缓存均使用 bf16 ./llama-server -m /path/to/model.gguf -c 8192 --cache-type-k bf16 --cache-type-v bf16 # 只将 K 缓存改为 bf16V 缓存保持默认 f16 ./llama-server -m /path/to/model.gguf --cache-type-k bf16 # 经典 CLIllama-cli / llama-perplexity 等同样适用 ./llama-cli -m /path/to/model.gguf -n 256 --cache-type-k bf16 --cache-type-v bf16参数说明默认值及含义见 docs/parameters.md 的 KV Cache 一节参数说明默认值-ctk, --cache-type-k TYPEK 缓存的存储类型f16-ctv, --cache-type-v TYPEV 缓存的存储类型f16-fa, --flash-attn是否启用 Flash Attentionon可显式auto/on/off在参数解析层面common/common.cpp将这些字符串在llama_model_params与llama_context_params初始化阶段统一转换为ggml_type见 common/common.cpp 中-ctk/-ctv的处理与kv_cache_type_from_str的调用因此从llama-server、llama-cli到llama-perplexity等所有入口的行为一致。关于 Flash Attention 的联动PR #69 的标题是“Allow bf16 kv-cache”但 KV Cache 类型与 FA 存在耦合在 src/llama.cpp 的上下文初始化逻辑中非 FA 模式下 V 缓存只允许f16与bf16两种类型而 K 缓存可以放宽到量化类型如q8_0if (model-arch ! LLM_ARCH_OPENPANGU params.type_v ! GGML_TYPE_F16 params.type_v ! GGML_TYPE_BF16 !params.flash_attn) { LLAMA_LOG_ERROR(%s: V cache quantization requires flash_attn\n, __func__); return nullptr; }因此如果你希望在关闭 FA 时使用 bf16 V 缓存这是被允许的但如果尝试使用比 bf16 更低位的量化 V 缓存则必须开启 Flash Attention。这一约束从源码结构看是因为非 FA 的注意力实现尚不支持 V 缓存的量化读取。五、源码佐证bf16 在存储与转换链中的位置1. 合法 KV Cache 类型集合在 src/llama.cpp 的 KV Cache 相关校验中bf16 与 f16、q8_0 等一起被明确列为合法类型。例如针对 DeepSeek4 架构的 K 缓存约束if (model-arch LLM_ARCH_DEEPSEEK4 params.type_k ! GGML_TYPE_F16 params.type_k ! GGML_TYPE_BF16 params.type_k ! GGML_TYPE_Q8_0) { LLAMA_LOG_ERROR(%s: DeepSeek4 K-cache supports only F16, BF16, and Q8_0 (requested %s)\n, __func__, ggml_type_name(params.type_k)); return nullptr; }这印证了 PR #69 之后bf16 已成为 KV Cache 类型体系中一等公民并与架构如 DeepSeek4的缓存设计直接挂钩。2. CUDA 上的类型转换路径作者在 PR 描述中提到 CUDA 上“缺少某个转换”这正是 bf16 缓存数据参与 CUDA 计算前的必经之路。在 ggml/src/ggml-cuda/convert.cu 中GGML_TYPE_BF16出现在多个转换分支如 bf16→f16、bf16→f32 等而在 ggml/src/ggml-cuda/cpy.cu 中同样存在 f32/f16 与 bf16 之间的相互拷贝实现。这意味着bf16 KV Cache 在 CUDA 后端依赖这些转换 kernel 才能参与注意力计算任何缺失的转换分支都会导致结果偏离表现为精度退化到 fp16 水平这与作者在 PR 描述中观察到的现象完全吻合。从当前代码看这些转换路径已经齐备bf16 可以正常参与 CUDA 前向计算。3. CPU 路径为何无损CPU 端ggml 标量/SIMD 实现对 bf16 通常先提升为 fp32 再参与矩阵乘与注意力计算中间不经过有损的二次量化。配合 bf16 与 fp32 相同的指数范围CPU 上 bf16 KV Cache 与更高位宽 PPL 一致的现象在代码层面可以得到合理解释精度损失仅来自尾数截断而对注意力打分贡献显著的是数值的数量级而非低阶尾数位。六、使用建议与适用前提基于 PR #69 的结论与当前仓库的实现状态给出如下实操建议CPU 推理优先考虑 bf16作者实测 CPU 上 bf16 与更高位宽 PPL 一致因此追求显存/内存节省时可放心使用--cache-type-k bf16 --cache-type-v bf16CUDA 上谨慎对照验证PR #69 明确记录了 CUDA 端 bf16 结果约等于 CPU fp16 水平的历史现象虽然当前仓库已补齐相关转换路径但如果你特别在意输出质量建议用llama-perplexity在同一模型上对比f16与bf16的 PPLV 缓存量化与 FA 的约束非 FA 模式下 V 缓存仅支持f16/bf16若需要q8_0等量化 V 缓存请开启--flash-attn分层混合配置仓库还支持按层指定缓存类型如--cache-type-k-first TYPE,N、--cache-type-k-last TYPE,N、--cache-type-v-first、--cache-type-v-last可将首/尾若干层的 K、V 缓存设为 bf16 或更高精度其余层用量化类型在内存与质量之间细粒度调优见 common/common.cpp 参数表与 docs/parameters.mdDeepSeek 架构注意DeepSeek4 的 K 缓存只接受f16、bf16、q8_0三种类型且无独立 V 缓存指定其他 V 缓存类型会被忽略或报错见 src/llama.cpp 校验逻辑。七、总结PR #69 是 ik_llama.cpp 在 KV Cache 存储类型体系上的一次关键开启它让 bf16 成为所有受支持平台上可用的 KV Cache 类型并留下了一个诚实的工程观察——CPU 上 bf16 精度无损而 CUDA 上最初因缺少转换路径导致精度回落。时至今日bf16 已经深度融入仓库的 KV Cache 类型校验src/llama.cpp与 CUDA 数据转换实现ggml/src/ggml-cuda/convert.cu、ggml/src/ggml-cuda/cpy.cu并可与分层缓存、Flash Attention、量化 K/V 缓存等机制组合使用。对于需要在内存受限环境下拉长上下文、且希望在 CPU 上不牺牲精度的用户bf16 KV Cache 是一个经过实测验证的稳妥起点。赞分享人工智能大模型推理引擎本地部署模型量化模型优化【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp点击查看免费下载相关推荐ik_llama.cpp CUDA 后端 BF16 支持从 PR 40 到源码级实现解析ik_llama.cpp CUDA 后端 BF16 支持从 PR 40 到源码级实现解析 导读 本文围绕 ik_llama.cpp 仓库早期的一则关键 PR人工智能大模型推理引擎本地部署模型量化模型优化ik_llama.cpp PR 265 解析为 FlashMLA-2 补齐 CPU 端 Q8_0 KV Cache 的连续转置支持ik_llama.cpp PR 265 解析为 FlashMLA 2 补齐 CPU 端 Q8_0 KV Cache 的连续转置支持 导读 本文以 ik_lla人工智能大模型推理引擎本地部署模型量化模型优化3步快速上手Appwrite隧道代理Fork项目到节点上线的保姆级部署教程3步快速上手Appwrite隧道代理Fork项目到节点上线的保姆级部署教程 Appwrite隧道代理Appwrite是一个专门适配 Appwrite Fu人工智能大模型推理引擎本地部署模型量化模型优化上一篇如何3分钟快速启动Yi-1.5-6B-Chat零基础友好的本地部署教程 下一篇Nacos域名包含register导致无法登录的问题分析与解决创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表