04 稳定性与性能调优实录:OOM 崩溃、并发槽位、前缀缓存与 DSpark 调参

文章目录

  • [04 稳定性与性能调优实录:OOM 崩溃、并发槽位、前缀缓存与 DSpark 调参](#04 稳定性与性能调优实录:OOM 崩溃、并发槽位、前缀缓存与 DSpark 调参)
    • [1. 事故:长会话把显存顶爆(CUDA OOM)](#1. 事故:长会话把显存顶爆(CUDA OOM))
    • [2. 取舍:ncmoe(专家上 CPU)调节阀](#2. 取舍:ncmoe(专家上 CPU)调节阀)
    • [3. 可用性事故:单槽串行 + 大系统提示词](#3. 可用性事故:单槽串行 + 大系统提示词)
      • [`--cache-reuse 256`(跨请求前缀复用)](#--cache-reuse 256(跨请求前缀复用))
      • [`-np 2`(双槽位 + 连续批处理)](#-np 2(双槽位 + 连续批处理))
    • [4. DSpark 草稿调参:n_max 3 → 5](#4. DSpark 草稿调参:n_max 3 → 5)
    • [5. 思考控制通道实测(客户端集成必读)](#5. 思考控制通道实测(客户端集成必读))
    • [6. 与官方建议对齐清单](#6. 与官方建议对齐清单)
    • [7. 现网最终配置(速查)](#7. 现网最终配置(速查))

04 稳定性与性能调优实录:OOM 崩溃、并发槽位、前缀缓存与 DSpark 调参

《DeepSeek-V4-Flash 本地部署与公网服务化》系列 · 第 ④ 篇 / 共 5 篇

① 硬件选型与 llama.cpp 部署 | ② API 鉴权与腾讯云公网桥接 | ③ 多协议支持:Anthropic 与 Responses API | ④ 稳定性与性能调优实录(本篇) | ⑤ 客户端接入:pi 与各类 SDK
本篇是上线后 24 小时内踩的坑与调优全过程,全部附实测数据。结论先行:./serve.sh 8081 524288 4 1 2(DSpark n_max=5 + ncmoe=4 + 双槽位 + cache-reuse)是这台 192GB 机器上速度/稳定/并发的最优点。

1. 事故:长会话把显存顶爆(CUDA OOM)

现象:公网请求突然全部 502(nginx Bad Gateway)。

定位:

  • 502 = nginx 连不上上游 → 跳板机 8081 隧道还在,但隧道尽头没东西了 → llama-server 进程已死,tmux 会话 ds 消失。

  • 排除网络层:隧道 autossh 进程健在;iptables 的 ! -i lo 规则正确(回环放行、丢包数 0)。

  • 日志 /tmp/serve_dspark.log 尾部铁证:

    11.31.561.655 E CUDA error: out of memory
    ggml_cuda_error ← ggml_cuda_pool_vmm::alloc
    ← argsort_f32_i32_cuda_cub ← ggml_cuda_op_top_k ← ... ← llama_decode

崩溃在 top_k 采样的 argsort 显存分配 。DSpark 全 GPU 档(ncmoe=0)每卡只剩 ~2GB 余量(01 篇的显存核算),随着会话上下文增长、KV cache 膨胀,某个 decode 步骤的采样 scratch 分配就越过了红线。llama.cpp 的崩溃处理器用 gdb 抓了完整 backtrace 写进日志,对定位帮助很大(现场备份在 /tmp/serve_dspark.log.crash.oom)。

教训 :--fit off + 理论核算通过 ≠ 运行时安全------KV cache 是随会话长度动态增长的,余量要按"最长会话"而不是"启动时"来留。

2. 取舍:ncmoe(专家上 CPU)调节阀

-ncmoe N 把前 N 个 MoE 专家层放到 CPU(权重 mmap,随用随读),是最有效的显存阀门:

配置 decode 显存/卡 结论
ncmoe=0 45.9 tok/s 43--48 GB(余量 ~2GB) 最快,但长会话 OOM 实锤
ncmoe=4 25.3 tok/s 36--46 GB(余量 3--13GB) 稳定,速度打 55 折

两个容易误读的现象(当时用户也疑惑过):

  • 内存/CPU"没变化"不代表没生效 :CPU 专家权重走 mmap,常驻 page cache(free 的 buff/cache 列,186GB 里就有它),不进进程 RSS;CPU 只在生成 token 的瞬间工作,空闲时是 0。判断依据是显存确实降了 + 日志有 tensor overrides to CPU are used with mmap enabled。
  • ncmoe=4 时务必配 numactl --interleave=all(双路 EPYC 8 个 NUMA 节点,避免单节点带宽热点)。

3. 可用性事故:单槽串行 + 大系统提示词

现象:在一个 pi 会话正常使用时,另一个会话发请求"很久都没有反应"。

定位(看 llama-server 的 slot 日志):

复制代码
task 704 | prompt processing, n_tokens = 49152 ... 167936
         t = 101s → 450s,吞吐 485 → 368 tok/s 一路递减

两个叠加问题:

  1. -np 1 单槽串行:一个请求的 prefill + 生成没跑完,其它请求全部排队,零反馈。
  2. 大 prompt prefill 昂贵 :pi 这类 agent 客户端的系统提示词 + 工具定义 + 会话历史动辄 80K--170K tokens;168K 的 prompt 光 prefill 就要 7.5 分钟 (吞吐随上下文变长递减,attention 成本上升)。而且之前响应里 cached_tokens 一直是 0~2------同样的系统提示词每次请求都从头算。

药方:

--cache-reuse 256(跨请求前缀复用)

把 KV cache 中 ≥256 token 的公共前缀复用给新请求。实测:同一个 ~2050 token 的系统提示词,第二请求 cached_tokens: 1022------一半 prefill 直接跳过。pi 的系统提示词在所有请求/会话间共享,收益巨大。

注意:开启后日志有警告 cache_reuse is not supported by this context, it will be disabled------指的是 DSpark 草稿模型的上下文不支持,主模型的前缀复用不受影响(实测 cached_tokens 正常),属于良性警告。

-np 2(双槽位 + 连续批处理)

-c 524288 -np 2 = 两个 256K 槽位,llama.cpp 的 continuous batching 会把一个槽位的 prefill 与另一个槽位的 decode 混批,多会话不再互相堵死。代价:单会话上下文上限 512K → 256K(槽位间静态平分),客户端的 contextWindow 要同步调小,否则超出会被服务端硬顶回来。

意外收获:总 KV 不变,但显存反而更省(GPU1 余量 2.9 → 9.8GB)------单槽 512K 时某些缓冲区按满配 ctx 分配。

4. DSpark 草稿调参:n_max 3 → 5

官方模型卡的 vLLM 配置用 num_speculative_tokens: 7;llama.cpp 的 --spec-draft-n-max 上限是 5(草稿训练块大小,日志里 block_size=5)。实测(同一路径、同类代码生成任务):

n_max decode 接受率 备注
3 25.3 tok/s 70%(mean len 3.10) 原配置
5 34.1 tok/s(+35%) 44%(mean len 3.75) 现网配置,显存无变化

接受率"下降"是正常摊薄------每步多提 2 个候选 token,命中率自然低,但每步净接受的 token 更多,wall-clock 才是真相。

5. 思考控制通道实测(客户端集成必读)

官方模型卡写明 reasoning_effort 只有 low / high / max 三档。对 llama-server 逐个实测(--reasoning-format deepseek 模式下):

请求字段 结果
reasoning_effort: low/high/max ✅ 接受(顶层或 chat_template_kwargs 内都行)
reasoning_effort: medium/minimal/none/off ⚠️ 200 但静默忽略(回退默认思考)
reasoning_effort: disabled ❌ 关不掉思考(reasoning_content 照出)
thinking: {type: "disabled"}(DeepSeek 官方 API 风格) ❌ 被忽略,仍思考
chat_template_kwargs: {enable_thinking: false} ✅ 唯一有效的关思考通道
两者同传(enable_thinking:false + reasoning_effort:max) ✅ enable_thinking 胜出

一句话:档位用 reasoning_effort(low/high/max),开关用 chat_template_kwargs.enable_thinking,别指望 DeepSeek 官方 API 的 thinking 字段。客户端映射详见 05 篇。

6. 与官方建议对齐清单

官方模型卡建议 落地
temperature=1.0;agentic top_p=0.95、其它 top_p=1.0 写入客户端 samplingParams(pi 是 agentic 场景,用 0.95)
reasoning_effort = low/high/max 客户端档位映射只发这三个值
high/max 档最大输出 384K tokens 客户端 maxTokens 设 32768(稳妥值,可按需上调)
DSpark num_speculative_tokens: 7 llama.cpp 上限 5,已调到 5
无 Jinja 模板(用 encoding/ 目录 Python 脚本编码消息) llama.cpp 内置 DeepSeek V4 模板,无需关心

7. 现网最终配置(速查)

bash 复制代码
./serve.sh 8081 524288 4 1 2
# port=8081, ctx=512K(2槽×256K), ncmoe=4, dspark=1(n_max=5), np=2
# + --cache-reuse 256 + --api-key-file

decode 34.1 tok/s,显存余量 9.8--22.9GB/卡,多会话并发,同前缀 prefill 减半。从"最快但会崩"(46 tok/s @ ncmoe=0)到"稳定且够快",这笔交易是划算的。


上一篇 :03 多协议支持 · 下一篇 :05 客户端接入:pi 与各类 SDK

相关推荐
未济3 天前
linux 配置环境变量
linux
傲世仙尊3 天前
目录即文件-Ext文件系统收尾篇
linux·c语言
虎头金猫3 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
_艾伦 耶格尔.3 天前
进程间通信
linux
AI职业加油站3 天前
AI智能体应用工程师证书:政策红利下的职业新风口
大数据·运维·人工智能·学习·职场发展
Liuqy-053 天前
Linux IO编程——静态库、动态库
linux
此冬歌咏3 天前
K8s 节点故障实战:优雅驱逐 31 秒,硬故障 331 秒,以及那个永远 Pending 的 Pod
运维·k8s
彧azz3 天前
Linux 环境下 Redis 学习总结:数据类型、持久化、锁、事务、主从与缓存问题
linux·redis·笔记·学习·面试
-梅3 天前
linux(8) 软硬链接
linux·运维·服务器
全栈弄潮儿²⁰²⁴3 天前
AI Agent 开发实战(30):限流、缓存与成本控制
人工智能·gpt·缓存·agent·限流·agi·成本控制