ik_llama.cpp 中的 DeepSeek 批处理性能优化:PP/TG 优化计算图切换阈值分析与实战调优
ik_llama.cpp 中的 DeepSeek 批处理性能优化PP/TG 优化计算图切换阈值分析与实战调优【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp本篇技术指南聚焦 ik_llama.cppllama.cpp 的性能优化分支中一次针对 DeepSeek 系列模型批处理batched processing速度的专项优化——PR #282。文章以该 PR 的完整研究过程为主线剖析PP optimized与TG optimized两类 MLA 计算图在批处理场景下的性能差异、源码中的切换逻辑pp_opt阈值并给出可复现的基准测试命令与实测数据。读完本文你将理解 DeepSeek 批处理吞吐量为何会在特定 batch size 出现断崖式下降掌握用llama-batched-bench、llama-bench、sweep-bench定位与验证该问题的方法以及当前仓库源码中采用的 128 token 切换阈值的来龙去脉。一、问题现象batch size 从 16 跳到 20 时的性能悬崖在 PR #2822025-03-23 提出中作者 ikawrakow 针对社区用户 saood06 在 PR #277 的讨论 中报告的批处理性能下降问题展开调查。使用 DeepSeek-Lite 模型运行llama-batched-bench时作者观察到当 batch size 从 16 增加到 20 时吞吐量出现戏剧性的急剧下滑。复现该问题的原始命令行如下./bin/llama-batched-bench -m junk1.bin -npp 512 -ntg 128 -npl 4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120 -pps -fmoe -fa -mla 3 -t 16参数含义与 examples/batched-bench/README.md 中的用法一致参数含义-npp每个序列的 prompt 处理 token 数此处固定 512-ntg每个序列的文本生成 token 数此处固定 128-npl并行序列batch数量列表这里以 4 为步长从 4 扫到 120-pps采用并行序列parallel sequences批处理模式-fmoe启用 MoE 专家处理优化-fa启用 Flash Attentionik_llama.cpp 中默认开启-mla 3启用 MLAMulti-head Latent Attention第 3 级实现-t 16使用 16 个线程初始调查曾怀疑是线程间工作分配出了问题但最终定位到根因——问题出在计算图的构建方式上。二、根因定位n_token n_head触发的 PP optimized 切换经过排查性能悬崖的真正原因是当n_token n_head时代码会从 TG optimizedtext generation 优化切换到 PP optimizedprompt processing 优化处理路径。这一优化来自主线上游 llama.cpp 的 PR #11446。切换后MLA 注意力从 Flash Attention 的Dk 576, Dv 512形态变为Dk 192, Dv 128形态代价是需要额外执行两次矩阵乘法在压缩的 latent KV 表示上通过wk_b、wv_b矩阵展开出完整的 K、V。对 DeepSeek-Lite 而言n_head 16而-npl以 4 为步长递增因此 batch size 20 恰好是n_token n_head首次成立的位置——这就是性能断崖出现在 16 与 20 之间的直接原因。作者也坦承并不清楚当初选择n_token n_head作为切换点的具体依据但它显然在批处理场景下严重损害了性能。源码佐证当前仓库中的pp_opt判定逻辑上述分析与当前仓库源码完全吻合。在 src/graphs/build_deepseek2.cpp 中DeepSeek2 系列含 DeepSeek-V3/R1、DeepSeek-Lite的 MLA 计算图构建函数中有明确注释与判定// whether to use n_tokens as the matrix dimension during multiplication or n_head // n_tokens is higher during prompt processing, this allows to optimize for this case bool pp_opt n_tokens 128 lctx.cparams.mla_attn 1;可以看到PR #282 的最终方案n_tokens 128阈值已合入当前仓库。同时该条件还有两个附加约束lctx.cparams.mla_attn 1仅当 MLA 实现级别大于 1 时才启用 PP 优化-mla 3是 ik_llama.cpp 的默认值见 docs/parameters.md在分片split注意力路径中还存在k_pp_opt_min_kv 1024的 KV 缓存长度下限src/graphs/build_deepseek2.cpp即n_kv 1024且模型具备wk_b/wv_b/wk_b_pp张量时才会走 PP optimized 的物化 K/V分支// pp_opt (mla 1, n_tokens 128, n_kv k_pp_opt_min_kv): materialize // per-rank K/V from the latent cache and use standard flash_attn instead of // FlashMLA-3 absorb. constexpr int k_pp_opt_min_kv 1024; const bool tp_pp_opt pp_opt (int)n_kv k_pp_opt_min_kv model.layers[il].wk_b model.layers[il].wv_b model.layers[il].wk_b_pp;同样的 128 token 阈值也出现在 BailingMoe3 架构的图构建中src/graphs/build_bailingmoe3.cppconst bool pp_opt n_tokens 128 lctx.cparams.mla_attn 1;PP optimized 与 TG optimized 的图级差异从 src/graphs/build_deepseek2.cpp 的build_deepseek2_layer_attention中可以看到两种路径的核心差异PP optimizedmla_attn 1 flash_attn pp_opt先从 KV cache 中取 latent 压缩表示kv_cache_nope通过wkv_b矩阵乘法物化出完整的k_nope与vkv_f32 ggml_mul_mat(ctx0, wkv_b, kv_cache_nope)再拼接 rope 部分后调用ggml_flash_attn_ext。这是标准的 FlashMLA 吸收之外的多步展开多头计算按n_head/n_max_head迭代进行TG optimized / absorb 路径else分支将q_nope与wk_b相乘把权重吸收进 query 侧q_nope2 ggml_mul_mat(ctx0, wk_b, q_nope)KV cache 直接以 latent 形态参与 Flash Attentionggml_flash_attn_ext(ctx0, q, kv_cache, kv_cache_lora, ...)最终仅用wv_b一次矩阵乘法还原输出。省去两次矩阵乘法但矩阵维度以n_head为主。用n_tokens还是n_head作为矩阵主维度决定了哪种路径更快prompt 很长时n_tokens远大于n_headPP optimized 更有利而 batch 较小或生成阶段n_tokens接近n_head甚至为 1时TG optimized 避免了多余矩阵乘法反而更快。三、性能对比实验PP optimized vs TG optimized为了验证切换点是否合理作者对比了 DeepSeek 在两种计算图下的 prompt 处理性能llama-bench分别固定pp_opt true与pp_opt falseTG optimized 在 prompt 长度不超过 64 token 时优于 PP optimized在 128 token 时二者差距已经不大。也就是说把切换阈值从n_token n_headDeepSeek-Lite 下即 16提高到n_prompt 128可以在小 batch 区间完全规避性能下降而在大 batch 区间损失极小。四、实测验证DeepSeek 671B IQ4_K_R4 的三组对比数据PR 讨论中saood06 按作者要求在 DeepSeek 671BIQ4_K_R4 量化约 353.53 GiB672.05B 参数48 线程 CPU 后端上完成了三组llama-bench基准测试这是判断 128 阈值是否合理的核心证据。4.1pp_opt n_tokens n_headPR 提议提交 d12f4a1 上的实验版本测试t/spp3210.30 ± 0.12pp6410.46 ± 0.66pp12811.25 ± 0.69pp1929.35 ± 0.34pp2569.46 ± 0.13pp3209.15 ± 0.29pp3849.43 ± 0.33pp44810.05 ± 0.16pp51210.30 ± 0.11pp5769.97 ± 0.20pp6409.62 ± 0.20pp7049.43 ± 0.14pp7689.51 ± 0.16tg1282.84 ± 0.004.2 固定pp_opt true始终启用 PP 优化测试t/spp329.15 ± 0.06pp649.91 ± 0.61pp12811.20 ± 0.38pp1929.25 ± 0.48pp2569.11 ± 0.29pp3208.96 ± 0.18pp3849.17 ± 0.12pp4489.93 ± 0.13pp51210.07 ± 0.31pp5769.66 ± 0.21pp6409.37 ± 0.10pp7049.26 ± 0.11pp7689.44 ± 0.20tg1280.99 ± 0.024.3 固定pp_opt false始终使用 TG optimized测试t/spp3210.09 ± 0.17pp6410.09 ± 0.53pp12810.50 ± 0.60pp1928.79 ± 0.37pp2568.70 ± 0.12pp3208.39 ± 0.17pp3848.74 ± 0.09pp4488.85 ± 0.15pp5129.48 ± 0.15pp5769.28 ± 0.02pp6408.89 ± 0.30pp7048.67 ± 0.10pp7688.69 ± 0.13tg1282.87 ± 0.004.4 三组数据的解读对照三张表可以得出几个关键结论小 promptpp32~pp64区间pp_opt falseTG optimized与pp_opt n_tokens n_head混合均维持在 10 t/s 以上而pp_opt truePP optimized在 pp32 仅 9.15 t/s——TG optimized 明显占优pp128 附近三种配置几乎打平11.25 / 11.20 / 10.50 t/s说明 128 正是性能交叉点附近pp192 之后PP optimized 与混合方案开始反超且差距逐渐拉开pp768 时约 9.44~9.51 vs 8.69 t/stg128生成阶段pp_opt true是灾难性的——0.99 t/s 对比另两种方案的 2.84~2.87 t/s接近 3 倍差距。这印证了 PR 中对 DeepSeek-R1 还有一处小改动以期减少性能凹陷的动机生成阶段绝不能误入 PP optimized 路径。综合来看对 DeepSeek-V3/R1128 头与 DeepSeek-Lite16 头而言128 token 都是合理的切换阈值。作者据此确认128 对 DeepSeek-R1 也不是一个坏选择。五、sweep-bench 实测DeepSeek-R1 的长上下文生成性能saood06 同时用sweep-benchexamples/sweep-bench/sweep-bench.cpp 提供的扫描式基准可对固定n_kvKV cache 长度扫描 prompt 处理与生成吞吐验证了 PR 对 DeepSeek-R1 的效果。早期结果显示改进颇具希望PP 阶段稳定在 5.15~10.32 t/sPPTGN_KVT_PP sS_PP t/sT_TG sS_TG t/s512128049.63610.3239.5743.2351212851257.0118.9843.2462.96512128102462.9868.1342.9162.98512128153663.4008.0844.0142.91512128204866.2287.7347.1672.71512128256072.5087.0646.5532.75512128307274.6166.8647.7722.68512128358480.6756.3550.9072.51512128409687.5585.8550.4322.54512128460888.5845.7853.8592.38512128512092.8385.5254.2772.36512128563299.4375.1554.2572.36表中S_PPprompt 处理吞吐随 KV cache 增长从 10.32 平滑衰减到 5.15 t/s未再出现断崖式跳水S_TG生成吞吐维持在 2.3~3.2 t/s 区间。PR 作者随后又推送了一次提交并说明该提交只影响B 128的结果不影响本次扫描范围因此无需中断重跑。六、如何在自己的机器上复现与验证6.1 复现批处理性能曲线batched-bench参照 PR 原始命令在编译好的 ik_llama.cpp 构建目录下执行模型路径替换为实际 GGUF 文件./bin/llama-batched-bench -m model.gguf -c 2048 -b 2048 -ub 512 -npp 512 -ntg 128 -npl 4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120 -pps -fmoe -fa -mla 3 -t 16观察 S_PP / S_TG 随-npl的变化曲线特别关注 16→20 附近是否还有凹陷。若使用 DeepSeek-Lite16 头类小头数模型旧版本n_token n_head阈值会在此处出现断崖当前仓库128 阈值则保持平滑。6.2 对比 PP/TG 两种计算图llama-bench按 PR 讨论中的方法编辑 src/graphs/build_deepseek2.cpp 将pp_opt分别固定为true/false重新编译再执行勿忘-mla 3 -fa 1 -fmoe 1与 CPU 后端参数./bin/llama-bench -m model.gguf -mla 3 -fa 1 -fmoe 1 -p 32,64,128,192,256,320,384,448,512,576,640,704,768 -t 48对照 pp32~pp768 的 t/s 曲线即可判断 128 阈值在你的硬件与模型组合上是否依然合适。注意每组配置的完整扫描耗时较长PR 讨论中单组约 50 分钟建议预留充足时间。6.3 扫 KV cache 长度sweep-bench若关心长上下文下生成阶段是否还有性能凹陷可参考 examples/sweep-bench/README.md 使用sweep-bench对n_kv进行扫描复现第四节中的 N_KV vs 吞吐量表。6.4 参数前提-faFlash Attention在 ik_llama.cpp 中默认开启-mla默认值为 3取值 0/1/2/3详见 docs/parameters.mdMLA 相关实验要求模型架构为 MLA 系DeepSeek2 / GLM_DSA / Mistral4 等-sm graph拆分路径要求-fa开启且-mla 1见 src/graphs/build_deepseek2.cpp若 GPU 层数小于总层数ngl n_layer且采用 graph 拆分模式mla会被强制为 3见 src/llama.cpp。七、结论与遗留问题PR #282 的核心成果可以总结为三点定位了批处理性能断崖的真实原因并非线程调度问题而是n_token n_head触发的计算图切换迫使小 batch 场景下走PP optimized路径并额外承担两次矩阵乘法将切换阈值从n_token n_head调整为n_tokens 128并叠加mla_attn 1与n_kv 1024分片路径约束使小 batch 与生成阶段保持 TG optimized 的高效形态通过 DeepSeek-Lite 与 DeepSeek 671B 的实测数据验证了 128 阈值的普适性同时暴露了pp_opt true在生成阶段tg128约 3 倍性能损失这一重要边界事实。PR 中作者也明确提出了遗留问题TG optimized → PP optimized 的交叉点是否依赖注意力头数还是可能依赖具体机器的常数——两种论点都能找到支持理由只能靠实测回答。当前仓库源码src/graphs/build_deepseek2.cpp以n_tokens 128作为答案对 128 头的 DeepSeek-V3/R1旧阈值n_token n_head本就不触发该 PR 主要惠及 DeepSeek-Lite 这类小头数模型的批处理场景对更大规模模型是否需要更高的切换阈值仍有待进一步基准测试探索。【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

VoiceCraft 上手指南:10 秒音频如何编辑已有语音,零样本 TTS 实操与避坑清单

VoiceCraft 上手指南:10 秒音频如何编辑已有语音,零样本 TTS 实操与避坑清单

VoiceCraft 上手指南:10 秒音频如何编辑已有语音,零样本 TTS 实操与避坑清单 【免费下载链接】VoiceCraft Zero-Shot Speech Editing and Text-to-Speech in the Wild 项目地址: https://gitcode.com/GitHub_Trending/vo/VoiceCraft 有声书录完了…

2026/9/19 6:19:51 阅读更多 →
无人机H∞鲁棒控制:Matlab实现与工程实践

无人机H∞鲁棒控制:Matlab实现与工程实践

1. 无人机姿态控制中的鲁棒性挑战去年调试四旋翼无人机时,我遇到了一个棘手问题:在室外飞行测试中,当遭遇突发侧风扰动时,基于PID的控制系统直接失控炸机。这种场景在实验室的完美环境下从未出现,却暴露了传统控制方法…

2026/9/19 6:19:51 阅读更多 →
Textual 中的 `<text-align>` CSS 类型:文本对齐值的完整指南

Textual 中的 `<text-align>` CSS 类型:文本对齐值的完整指南

Textual 中的 <text-align> CSS 类型&#xff1a;文本对齐值的完整指南 【免费下载链接】textual The lean application framework for Python. Build sophisticated user interfaces with a simple Python API. Run your apps in the terminal and a web browser. 项目…

2026/9/19 6:19:51 阅读更多 →

最新新闻

Turborepo 二进制入口深度解析:从 `turbo` crate 的薄封装看 Rust 迁移架构

Turborepo 二进制入口深度解析:从 `turbo` crate 的薄封装看 Rust 迁移架构

Turborepo 二进制入口深度解析&#xff1a;从 turbo crate 的薄封装看 Rust 迁移架构 【免费下载链接】turbo Build system optimized for JavaScript and TypeScript, written in Rust 项目地址: https://gitcode.com/gh_mirrors/tu/turbo 本篇文章以仓库中 crates/tur…

2026/9/19 7:16:14 阅读更多 →
STM32CubeMX+FreeRTOS实战:从零搭建LED闪烁任务

STM32CubeMX+FreeRTOS实战:从零搭建LED闪烁任务

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/19 7:16:14 阅读更多 →
ESP32音频abort残留问题:解码器状态重置与DMA清空实战

ESP32音频abort残留问题:解码器状态重置与DMA清空实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/19 7:16:14 阅读更多 →
BrewUI 评测:给 Homebrew 一个图形界面,轻松管理 Mac 软件包

BrewUI 评测:给 Homebrew 一个图形界面,轻松管理 Mac 软件包

1. 项目概述&#xff1a;BrewUI 是什么&#xff0c;以及我为什么盯上它用 Mac 做开发的人基本都躲不开 Homebrew。从装 Node、Python 这种运行时&#xff0c;到开个 wget、tmux 之类的小工具&#xff0c;我每天都要跟它打交道。但说实话&#xff0c;Homebrew 这个包管理器非常强…

2026/9/19 7:16:14 阅读更多 →
Chromium历史版本离线安装包下载与部署全攻略

Chromium历史版本离线安装包下载与部署全攻略

1. 为什么需要 Chromium 历史版本离线安装包做前端自动化、浏览器兼容性测试或者 Electron 桌面应用开发的朋友&#xff0c;大概率都遇到过这样的场景&#xff1a;某个线上问题只在特定版本的 Chromium 内核上复现&#xff0c;新版本浏览器早就修掉了&#xff1b;或者公司内网环…

2026/9/19 7:16:14 阅读更多 →
Civitai Orchestrator 工作流查询统一化:从双端点走向类型感知的单一路由

Civitai Orchestrator 工作流查询统一化:从双端点走向类型感知的单一路由

Civitai Orchestrator 工作流查询统一化&#xff1a;从双端点走向类型感知的单一路由 【免费下载链接】civitai A repository of models, textual inversions, and more 项目地址: https://gitcode.com/GitHub_Trending/ci/civitai 导读 本文围绕 Civitai 主站&#xf…

2026/9/19 7:15:14 阅读更多 →

日新闻

BP神经网络时序预测:滑窗长度与多窗口平均策略

BP神经网络时序预测:滑窗长度与多窗口平均策略

简介&#xff1a;面向机器学习、深度学习与数据建模学习者的一份完整研究文献&#xff0c;聚焦BP神经网络在农业产量预测中的应用。文档以1980—2018年全国棉花产量为样本&#xff0c;系统讲解数据归一化处理、激活函数原理、多层神经网络结构搭建及训练流程&#xff0c;展示敏…

2026/9/19 0:00:30 阅读更多 →
Transformer训练实时监控实战:基于MindSpore的损失曲线可视化方案

Transformer训练实时监控实战:基于MindSpore的损失曲线可视化方案

上个月调一个Deformable DETR模型&#xff0c;在单卡上要跑将近两天。第二天早上我下意识打开终端翻日志&#xff0c;发现loss从凌晨两点就开始往上爬&#xff0c;一路从0.8涨到1.35&#xff0c;整整六个小时没人发现。那六个小时的训练不仅白跑&#xff0c;还霸占着卡——等于…

2026/9/19 0:00:30 阅读更多 →
OpenCloud 中的 Go 类型安全转换库 spf13/cast:从零值回退到泛型 API 的完整实战指南

OpenCloud 中的 Go 类型安全转换库 spf13/cast:从零值回退到泛型 API 的完整实战指南

OpenCloud 中的 Go 类型安全转换库 spf13/cast&#xff1a;从零值回退到泛型 API 的完整实战指南 【免费下载链接】opencloud &#x1f324;️ OpenCloud is the open source platform for file management, sharing and collaboration. Simple and sovereign. 项目地址: htt…

2026/9/19 0:00:30 阅读更多 →

周新闻

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南&#xff1a;掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验 【免费下载链接】ai The AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and ag…

2026/9/19 3:59:36 阅读更多 →
Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战&#xff1a;基于 Intl 的本地化数字格式化 【免费下载链接】refine A React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility. 项目地址: https://gitcode.com/GitH…

2026/9/19 3:53:08 阅读更多 →
Flutter应用改名全指南:从Android到iOS的配置与工具实践

Flutter应用改名全指南:从Android到iOS的配置与工具实践

刚接一个外包项目时&#xff0c;甲方要求把工程里临时用的应用名改成正式产品名。我本来觉得“改名”这种小事&#xff0c;打开配置文件改一行不就完了&#xff1f;结果真动手才发现&#xff0c;Flutter项目里“应用名称”根本不是一处配置&#xff0c;而是一整套散落在 Androi…

2026/9/19 4:02:43 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践&#xff1a;原型怎样变成可用功能分类&#xff1a;[AI/大模型]细分主题&#xff1a;AI 增强型 CI/CD 流水线自动化与 GitOps 实践&#xff1a;Agent 工作流、工具调用与任务拆解&#xff1a;从原型到生产的验收清单很多团队在尝试用大…

2026/9/16 22:31:27 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战&#xff1a;复盘记录怎样真正派上用场分类&#xff1a;[工程技术]细分主题&#xff1a;Kubernetes 生产环境运维与排障实战&#xff1a;可复制的项目复盘模板与决策记录大部分团队的事故复盘报告&#xff0c;最后都变成了躺在 Confluence 或钉…

2026/9/15 21:39:18 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理&#xff1a;核心链路应该先拆哪一步分类&#xff1a;[工程技术]细分主题&#xff1a;Docker 容器化技术与镜像安全管理&#xff1a;核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用&#xff08;包含 Web 接口、后台…

2026/9/16 22:32:59 阅读更多 →