-
-
-
不错,散热有没有问题?之前论坛有个帖子用了v4的cpu加ddr3的内容,说是温度特别高,他退货了,如果你这个方案肯行,我也要换了,我只有一张xtx7900
-
不错,散热有没有问题?之前论坛有个帖子用了v4的cpu加ddr3的内容,说是温度特别高,他退货了,如果你这个方案肯行,我也要换了,我只有一张xtx7900
-
-
,系统 取消固定了此主题
-
https://lcz.me/topic/2671/9
今天发现这个大神的帖子,超了作业,提升很大实测已经全部完成,数据写进运维手册第 9 节了。下面是优化前 vs 优化后的完整对比。
-
prefill:处理长提示词(tok/s,越高越好)
提示词长度 优化前 0.1.45 原配置 0.1.45 只把块调到 32K fork RDNA3
1 万 token 1,019 1,263(+24%) 2,090(+105%)
8 万 token 1,281 1,429(+12%) 3,129(+144%)
三次重复测量误差仅 ±0.3%(1,018.7 / 1,019.4 / 1,021.5),这组数字很硬。 关键结论:光把 prefill 块从 8192 调到 32768 只拿到 +24%/+12%,剩下的大头是 fork 的 RDNA3 内核真本事——我专门做了这个隔离实验,否则会把功劳记错。 -
decode:生成速度(tok/s,固定 seed、6 次中位数)
优化前 优化后 提升
短提示 66.5 74.1 +11.4%
3.2 万 token 提示 64.1 77.4 +20.7% -
真实 agent 循环(12 轮,每轮追加约 830 token,上下文涨到 2.68 万)
优化前 优化后 倍数
首轮冷 prefill 15.12 s 8.01 s 1.89×
稳态每轮 2.70 s 1.59 s 1.70×
12 轮总计 46.37 s 26.32 s 1.76×
这个才是你日常体感对应的场景(大部分请求是"恢复检查点 + 追加一小段")。 -
一个重要的反向验证
我担心 fork 缺 --prompt-cache-spread(0.1.45 有,是我上次修长任务缓存抖动的开关),专门测了缓存命中:两边逐条完全相同(cached token 数 8396 / 28551 / 75576 一模一样)。所以这个差异在本机测不出影响,不是迁移障碍。 -
折算到你那个 140 步长任务
按之前统计的成本结构(prompt 读 5.12 h + decode 15.32 h = 20.4 h):
prompt 部分:5.12 h → 约 2.3 h
decode 部分:15.32 h → 约 13.4 h(decode 只快 12-16%,且它占 75%)
合计约 20.4 h → 15.7 h,省 23%
也就是说:prefill 快 2 倍多非常可观,但你的长任务瓶颈其实在生成 token 数,换引擎能省四分之一,真正的大头还是要靠少生成。- 现在的状态
fork 正在跑(strata-fork.service),strata.service 已停止但仍是开机默认
所以现在重启会回到 0.1.45,不会留下半吊子状态
回滚一条命令:systemctl stop strata-fork && systemctl start strata
0.1.45 的配置我也加了 --prefill auto:32768(白捡 +24%/+12%,无代价),备份在 strata-iq3_s.json.before-prefill32k
代价:fork 是 0.1.43(比 0.1.45 旧)、没编译 vision(源码在 tools/vision/strata_vision.cpp,需要时能补编)、多占 16 GB 源码。
对比完我在配置图片能力,一会测试一下试试。
-
-
-
-
最近任务都积压在本地模型里,发现爆显存越来越频繁。先给一个DeepSeek的解决办法,我抄了一下,看看效果,如果改了继续爆我再找原因再找方法。
针对你的 Qwen3.8-Flash-Next IQ3_S 模型和 7900 XTX (24GB) 的配置,结合你之前“强制常驻”导致崩溃的背景,问题的核心在于让显存调度更“柔和”。IQ3_S 量化版本身在 24GB 显存上跑 262K 上下文是可行的,峰值占用约 17.97 GiB,但 MTP 投机解码和强制常驻会打破这个平衡。
下面是一份基于你现状的参数修改清单,核心是去掉硬性限制,让引擎动态管理,在保持 MTP 加速的同时避免 OOM 崩溃。
️ 关键参数修改清单- 移除或降低 --kv-resident(最关键的一步)
操作:直接删除 --kv-resident 32768 这个参数。如果担心性能,可以逐步降低到 --kv-resident 16384 或 8192。
原因:IQ3_S 的 262K 上下文池完全有能力驻留在 24GB 显存中,但强制一次性钉住 32768 个 cell 会瞬间挤压 MTP 的生存空间。让 vLLM 根据实际显存水位动态管理 KV Cache,可以利用你 128G 大内存作为稳定缓冲,这是防止崩溃最直接的方法。
- KV Cache 量化:启用 q4_0
操作:在启动参数中添加 --kv-cache-dtype q4_0。
原因:这是在 7900 XTX 上经过验证的稳定配置,能显著降低长上下文下的显存压力。需要提醒的是,不要使用 fp8 量化,因为 RDNA3 架构没有原生 FP8 加速,会触发软件模拟导致严重降速。
- MTP 参数:固定投机深度为 3
操作:添加或修改参数为 --spec-draft-n-max 3(或 --spec-tokens 3)。
原因:在 24GB 显存下,投机深度 3 是速度与显存的黄金平衡点,能带来可观的加速,同时避免更高深度带来的额外显存开销和崩溃风险。
- 预填充分块:限制 --max-num-batched-tokens
操作:添加 --max-num-batched-tokens 3072 或 4096。
原因:这能有效削平长文本 Prefill 阶段瞬间的 CUDA 内存峰值,通常能直接释放约 1GB 的缓存余量,避免因瞬时内存暴涨导致的 OOM。
- (可选)微调 --gpu-memory-utilization
操作:默认 vLLM 在 ROCm 上保守使用 90% 显存,可以尝试设置为 --gpu-memory-utilization 0.92 或 0.95。
注意:这是一个微调选项。如果在移除 --kv-resident 后仍然崩溃,可以尝试;如果一切稳定,则无需改动。
️ 需要留意的平台特定风险
除了 OOM 崩溃,在你的平台(7900 XTX + ROCm)上,长上下文 + MTP 还有一个更隐蔽的陷阱:OOM 池排空(Pool Drain)后产生“垃圾输出”。有报告指出,当 KV 映射增长到显存耗尽触发 OOM 后,即便进程没有崩溃,后续的请求也可能持续生成乱码或无效内容,直到重启进程才能恢复。因此,预防 OOM 是首要目标。上述参数调整正是为了从根源上避免触发这个危险状态。
总结与推荐启动参数
综合以上建议,你的 vLLM 启动命令可以调整为类似以下结构(请根据你的实际路径替换模型路径):bash
vllm serve <你的模型路径>
--max-model-len 262144
--kv-cache-dtype q4_0
--spec-draft-n-max 3
--max-num-batched-tokens 4096 \已移除 --kv-resident 32768
其他你的自定义参数...
修改优先级:移除 --kv-resident > 添加 --kv-cache-dtype q4_0 > 固定 --spec-draft-n-max 3 > 限制 --max-num-batched-tokens。
你可以先尝试前两项,这通常足以解决大部分崩溃问题。如果调整后仍然遇到显存不足,可以再逐步加入后续的优化项。
- 移除或降低 --kv-resident(最关键的一步)
-
改完之后又崩了,发现一个bug,然后继续改,贴一下结果。
已经定位并修好了。下面是完整说明。结论
这不是"显存真的爆了",而是引擎在 prefill 阶段一个 GPU 内核发生非法内存访问(illegal memory access),进程直接退出,systemd 每 15 秒把它拉起来、再加载模型(约 3.5 分钟)——所以你看到的现象是"爆显存 / 重启不出来 / 发任务就报错",其实是崩溃-重启循环。日志里全程显存余量 120+ GiB、没有任何 OOM/分配失败记录,可以证实。
根因
那条报错在源码里只有一个产生点:
src/prefill/prefill.cpp:1616err = std::string("prefill: the draft layer's K/V: ") + cudaGetErrorString(cudaGetLastError());它位于
Prefill::draft_kv()的末尾同步点。这条路径是 E-9「草稿层(MTP 投机解码)prompt K/V 批量 pass」,只在单卡 + 草稿层 K/V 处于 ring 模式(你这份 config 里--kv-resident 20480 --mtp-window 4096正好让它走 ring)时才会执行——分卡/无 ring 时默认走的是草稿层自己的逐组安全 pass。我把整条链路(
kv_plan/qsa_state_init/kv_appendbatch 内核 /rope/ mrope 表 / embedding gather / snapshot 恢复)全部核过边界,在pos<262144时 page_table、row、host row_id 等下标都在界内,几何(head_dim 256、n_head_kv 2)也和模型匹配。也就是说:这是 E-9 在 ring 模式下一条长期存在的偶发越界/状态错乱路径(engine-rdna3.log.1里 11 月 1 日前就有 2 次同类崩溃,当前日志 7 次),近期变频繁和你的真实 agentic 快速流量(工具调用、读图、多会话缓存换入换出)有关。我用纯文本/长解码/vision/缓存复用/eviction 做了大量合成压测(repro2/3/4/6/7/8、t72,最长到 20 万 token)都复现不出来,说明它确实只在真实复杂流量下偶发。我做的修复(源码级)
单卡只有这一条批量 pass 不安全,而它相对安全 pass 只快约 0.8 秒/32K token。所以最稳妥的源码修复是:让
draft_kv在草稿层为 ring 时默认不再走批量 pass,回落到底层已验证的逐组安全 pass(多卡生产默认就走它)。唯一改动src/prefill/prefill.cpp的两行:// ring_ok 由"未设置=开启"改为"必须显式 =1 才开启" static const bool ring_ok = []{ const char* v=getenv("STRATA_MTP_BATCH_RING"); return v != nullptr && v[0] == '1'; }();这样
if (st.kv_mode != 0 && !(st.kv_mode == 2 && ring_ok))在 ring 时恒成立 →draft_kv直接 decline →generate.cpp回落到mtp.prefill(...)。那条唯一会报 "draft layer's K/V" 的代码路径从此不再执行。- 已重新编译:
build-hip/strata(ninja -C build-hip strata,rc=0,新二进制 12:21,strings已确认新逻辑编入)。 - 已重启服务:kill 旧 MainPID 触发 systemd 自动重启,新 server.py/engine 于 12:22:20 启动,
/health返回loaded:true。 - 备份在
/tmp/prefill.cpp.bak-fix;工作树仅M src/prefill/prefill.cpp。
验证结果(新二进制)
- 全新 60,270 token 长 prompt:成功,36.0s,
drafts 9/12 accepted——说明回落的安全 pass 算出的草稿层 K/V 是正确的,投机解码仍然生效。 - 12 个会话 × 10 轮 round-robin = 121 个请求(含图片、每轮切会话强制 park/evict churn):ok=121, fail=0。
- 新会话引擎日志零 illegal / error / K-V / stopped;server 日志持续正常
done,无引擎重启。全日志 "illegal memory access" 计数仍是 7(全是修复前的旧会话记录)。
影响与回滚
- 代价很小:草稿层 prompt pass 从批量改回逐组,60K prompt 大约慢 1~2 秒,对你日常使用几乎无感。
- 想回旧的快速路径(不推荐,根因未除):设
STRATA_MTP_BATCH_RING=1即可重新开启 ring 批量。 - 彻底回滚:
git checkout src/prefill/prefill.cpp重新编译重启。
建议
先按这个版本跑几天真实流量观察;若还想彻底恢复批量加速,正确的做法是基于上游
origin/main(比当前分支新 2202 个提交)重新审查 E-9 的 ring 实现或干脆升级到上游——我这边已确认当前分支里没有单独修这个崩溃的提交。要不要我顺手帮你把这次改动提交成一个 git commit(带说明),或者继续深挖 E-9 ring 批量那条内核的具体越界点(需要真机复现条件)? - 已重新编译:
版主审定:本帖设为精华,作者 +5 积分奖励,希望再接再厉!