尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

ik_llama.cpp CPU 端 Flash Attention 调优:DeepSeek-Lite 长上下文生成性能提升实践(PR 410)

ik_llama.cpp CPU 端 Flash Attention 调优:DeepSeek-Lite 长上下文生成性能提升实践(PR 410) ik_llama.cpp CPU 端 Flash Attention 调优DeepSeek-Lite 长上下文生成性能提升实践PR #410【免费下载链接】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 #410Better CPU FA performance for DeepSeek-Lite展开该 PR 针对 MLAMulti-head Latent Attention模型在纯 CPU、Q8_0量化 KV 缓存场景下对 CPU Flash Attention 内核进行调优显著改善了 DeepSeek-Lite 这类模型的长上下文 token 生成TG速度。读完本文你将了解如何用llama-sweep-bench复现上下文长度扫描基准测试、-fa/-mla/-rtr等关键参数的作用以及从源码层面理解 ik_llama.cpp 的 CPU FA 实现为何对 KV 量化类型与上下文长度敏感。一、PR 背景CPU 上 MLA 模型的注意力瓶颈DeepSeek 系列模型采用 MLA 注意力结构K 缓存存放的是压缩后的 latent 向量而非完整的 key 头配合 V 缓存参与注意力计算。在纯 CPU 推理时随着上下文变长每个生成 token 都要对整个 K 缓存做一次q·k^T点积 softmax 加权求和注意力计算成为 token 生成阶段的主要开销之一。PR #410 的核心结论引自 PR 描述该 FA 调优改善了DeepSeek-Lite在Q8_0KV 缓存下的 CPU TG 性能对更大的 DeepSeek 模型如 V3/R1 规模是否有正收益作者在提交时尚无法验证——因为作者手头没有可用的大模型测试环境基准测试使用Ryzen 7950XCPU被测模型为Q4_0量化的 DeepSeek-Lite复现命令为./bin/llama-sweep-bench -m $model -c 16384 -ub 1024 -t 16 -mla 3 -fmoe -fa -rtr各参数含义以 参数解析源码 中的定义为准参数含义-c 16384上下文窗口大小 16384-ub 1024每个 ubatch处理窗口大小 1024-t 16计算线程数 16-mla 3启用 MLA 注意力模式级别 3源码中为params.mla_attn取值 0–3见 common/common.cpp 中-mla, --mla-use选项-fmoe启用 fused MoE默认启用可用-no-fmoe关闭-fa启用 Flash Attention可取auto/on/off/0/1源码 common/common.cpp 第 1914 行附近-rtr运行时张量重排run-time repack当存在 interleave 变体时自动使用见 common/common.cpp 第 2216 行附近注意-fa也可以通过环境变量LLAMA_ARG_FLASH_ATTN设置且存在V 缓存被量化但未开启 FA的兜底逻辑——源码在 common/common.cpp 中有if (!mparams.flash_attn ggml_is_quantized(mparams.type_v))的判断保证量化 KV 场景下注意力路径正确。二、llama-sweep-bench上下文扫描基准工具PR 中的曲线与表格均由仓库自带的 sweep-bench 工具 产生。按 examples/sweep-bench/README.md 的说明它对整段上下文做扫描按每个 ubatch 大小的窗口分别采集性能指标而非对全上下文取平均因此能直观展示性能随上下文长度如何衰减。其基准流程为对上下文中的每个 ubatch 窗口 1. 生成 ubatch/4 个 token不完整生成以节省时间 2. 测量生成性能TG 3. 从 KV 缓存中删除已生成 token 4. 准备一批 ubatch 大小的随机 token 5. 处理该批并测量 prompt 处理性能PP输出指标PR 表格中的列名即来源于此列含义PP每个 ubatch 处理的 prompt token 数TG每个 ubatch 生成的 token 数N_KV当前 KV 缓存中 K 的 token 数本 PR 中为Q8_0量化T_PP sprompt 处理耗时即首 token 时间S_PP t/sprompt 处理速度T_TG s全部批次生成耗时S_TG t/s文本生成速度该工具还支持--output-format jsonl输出机器可读结果每行包含n_kv、t_pp、speed_pp、t_tg、speed_tg等字段便于脚本化对比。三、PR #410 与主分支的实测对比数据以下完整数据来自 PR #410 描述Ryzen 7950XQ4_0DeepSeek-LiteQ8_0KV 缓存PP1024TG256主分支mainPPTGN_KVT_PP sS_PP t/sT_TG sS_TG t/s102425601.488688.027.11235.99102425610241.674611.737.36134.78102425620481.788572.757.52434.02102425630721.951524.977.72833.13102425640962.104486.657.92732.29102425651202.276449.938.15231.40102425661442.483412.408.44130.33102425671682.841360.458.79529.11102425681922.794366.559.29427.54102425692162.974344.369.14228.001024256102403.130327.159.40427.221024256112643.328307.699.65426.521024256122883.499292.6710.07825.401024256133123.840266.7010.53624.301024256143363.886263.5310.96923.341024256153604.055252.5211.43022.40PR #410PPTGN_KVT_PP sS_PP t/sT_TG sS_TG t/s102425601.469696.867.12635.93102425610241.601639.657.32234.96102425620481.759582.037.44634.38102425630721.920533.477.67333.36102425640962.081491.987.72833.13102425651202.282448.647.85232.60102425661442.413424.337.99132.04102425671682.626389.958.12231.52102425681922.753372.028.23831.08102425692162.934348.978.39430.501024256102403.159324.178.53829.981024256112643.299310.448.66829.531024256122883.501292.478.81829.031024256133123.684277.988.96928.541024256143364.074251.379.08928.161024256153604.086250.639.16727.93数据解读短上下文N_KV ≤ 5120收益有限两者 TG 速度差异在 1 个 token/s 以内属于测量噪声范围长上下文收益随 N_KV 单调放大N_KV 从 0 增长到 15360 时主分支 TG 从 35.99 衰减到 22.40 t/s约 -38%而 PR 版本仅衰减到 27.93 t/s约 -22%。也就是说 PR 修复的主要是注意力成本随上下文线性增长部分的斜率这正是 FA 内核优化的典型特征PP 阶段同步受益长上下文下 prompt 处理速度S_PP也普遍高出主分支 5–10%因为长 prompt 的注意力计算同样走同一套 FA 路径。四、源码纵深CPU Flash Attention 的实现结构4.1 入口与 KV 类型支持ik_llama.cpp 的 CPU FA 实现位于 ggml/src/iqk/iqk_flash_attn.cpp核心入口为iqk_flash_attn_noalibi无 ALiBi 的 flash attention 计算。它对 K/V 缓存量化类型有明确的支持边界见supported_kv_types()同文件第 105–116 行附近默认支持F16、Q8_0、Q8_KV、Q6_0开启GGML_IQK_FA_ALL_QUANTS编译选项后额外支持Q4_0、Q4_1、IQ4_NLBF16 仅在 AVX512-BF16 环境下支持且要求 K/V 类型一致。这与 PR 描述的Q8_0KV 场景完全吻合Q8_0是 CPU FA 的一等公民类型精度损失小、内存带宽占用约为 F16 的一半是 DeepSeek 类大缓存模型在 CPU 上的推荐 KV 量化。4.2 针对 Q8_0 的 work buffer 特判iqk_fa_work_buffer_size()ggml/src/iqk/iqk_flash_attn.cpp 第 50–103 行为不同张量形状预计算多线程工作区大小。其中有两处与 PR 场景直接相关的特判可以推断 PR 的调优正落在这一类按形状分派的代码路径上// 批量查询nq 8且 K 为 Q8_0直接按整个 K 张量准备空间 if (Q-ne[1] 8 K-type GGML_TYPE_Q8_0) { size ggml_row_size(GGML_TYPE_Q8_0, K-ne[0]) * K-ne[1]*K-ne[2]*K-ne[3]; } // 单查询TG 场景nq 1且 K 行较多按线程切分 K 行 if (Q-ne[1] 1 ... K-ne[1]/32 1) { int nstep_k K-ne[1]/32; if (nstep_k 4*nth) { ... } // K 行足够多时每线程独占一段 int gcd_k simple_gcd(nstep_k, nth); ... // 否则用 GCD 划分避免线程负载不均 }这段结构揭示了 PR 关注的两个要点TG 场景Q-ne[1] 1是 N_KV 增长的直接受害者每生成一个 token单行 q 要与 N_KV 行 K 做点积K 行数越多线程间 K 行切分的粒度和均衡性就越关键。nstep_k 4*nth的分支让每线程持有连续 K 段提升缓存局部性GCD 分支则处理 K 行数与线程数不成整数倍的情况线程划分策略与 NUMA 强相关K 缓存分布在多路/多 NUMA 节点的内存中时哪些线程读哪些 K 段直接决定跨节点访问比例。PR 评论中作者也指出这一点见下文第五节。4.3 模板化的多形状 FA 内核实际计算内核按 K/V 头维度组合被拆分为多个模板实例位于 ggml/src/iqk/fa/ 目录包括iqk_fa_128_128.cpp、iqk_fa_192_192.cpp、iqk_fa_256_256.cpp、iqk_fa_512_512.cpp、iqk_fa_320_256.cpp等命名格式为Dk_Dv统一由 iqk_fa_templates.h 中的IQK_FA_CASE宏声明。MLA 模型的 K latent 维度较小如 128、192V 维度较小因此 DeepSeek-Lite 走的是对应维度组合的内核分支。PR 的FA tweak即针对这类内核在不同 N_KV 下的线程切分与缓冲策略做的调整。五、PR 讨论区的验证反馈与 NUMA 问题PR 合入前最终状态为 Closed2025-05-12 创建、2025-05-20 更新的讨论对结论的可迁移性提供了重要限定第三方实测未复现同等幅度的提升用户在 32K token其常规测试深度的两倍场景下用新构建 清缓存后启动 server观察到大致持平、可能略好但没有看到作者那种随上下文长度放大的大幅改进作者归因为 NUMA作者推测性能瓶颈与 NUMA 拓扑相关——自注意力计算时如果线程与 KV 缓存的 NUMA 亲和性不佳收益会被跨节点访存掩盖因此单路 NUMA 或 NUMA 亲和性良好的机器上可能看不到显著的性能提升对 TG 本地命中率的追问讨论中还提到 TG 阶段缓存局部命中率较高的测量结果作者追问该测量是在多大上下文下完成的——这提示复现该收益时上下文深度、CPU 拓扑、线程数三者必须同时固定否则不同测试之间的对比没有意义。从源码结构看NUMA 敏感性与 4.2 节的多线程 K 行切分逻辑一致K 段的线程分配顺序决定了跨 NUMA 内存访问模式。若要在多路 CPU 上获得该 PR 级别乃至更优的收益配合 OS 级 NUMA 绑定如numactl按节点绑定线程是合理的排查方向。六、实操要点小结复现基准用llama-sweep-bench并按 examples/sweep-bench/README.md 的示例传参重点对比不同N_KV下S_TG的衰减斜率而非单点数值参数组合MLA 模型DeepSeek 系列在 CPU 上建议同时使用-mla按模型支持的级别-fa-rtr fused MoE默认开启KV 缓存量化优先Q8_0预期管理该调优的收益在长上下文 单查询TG 多线程 K 缓存为 Q8_0的交集场景最明显且受 NUMA 拓扑影响短上下文、GPU 卸载或多 NUMA 未绑核的场景下提升可能不显著——这正是 PR 讨论中多方实测得出的结论进一步阅读CPU FA 入口 ggml/src/iqk/iqk_flash_attn.cpp、各形状内核 ggml/src/iqk/fa/、基准工具 examples/sweep-bench/sweep-bench.cpp、CLI 参数 common/common.cpp。【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表