NeoHorse-1 本地推理显存不够 / 先降上下文再换量化

文章导读
本地跑 NeoHorse-1 显存爆掉时,先把问题拆成「权重常驻」和「KV 缓存随上下文增长」两块,比直接换推理后端更容易定位。判断顺序建议是:固定量化版本、先把最大上下文压短,确认能稳定加载;如果压到能用了但不想牺牲上下文,再换更低比特量化;最后才去调推理后端的批处理和缓存策略。
📋 目录
  1. 壹 记录加载模型后的基础显存占用
  2. 贰 缩短上下文长度并观察峰值
  3. 叁 换成更低比特量化版本
  4. 肆 调整推理后端的批处理和缓存策略
  5. 伍 用同一段任务复测稳定性
A A

本地跑 NeoHorse-1 显存爆掉时,先把问题拆成「权重常驻」和「KV 缓存随上下文增长」两块,比直接换推理后端更容易定位。判断顺序建议是:固定量化版本、先把最大上下文压短,确认能稳定加载;如果压到能用了但不想牺牲上下文,再换更低比特量化;最后才去调推理后端的批处理和缓存策略。

显存不足通常来自两块:模型权重常驻和 KV 缓存随上下文增长。建议先固定量化版本,把最大上下文和批大小设到保守值,记录加载后空闲显存与单请求峰值;确认能稳定加载后,再逐档放大上下文。若仍不够,再换更低比特量化并复测输出连贯性。批处理与缓存策略属于第三层调整,改完必须用同一段输入复测,避免把截断或崩溃误判成显存问题。

记录加载模型后的基础显存占用

先把两种溢出分开:一种是权重本身放不进显存,加载阶段就报 out of memory;另一种是权重进去了,但请求变长后 KV 缓存把剩余空间吃光。前者只能靠换量化或换设备,后者可以先从上下文长度下手。

在加载前后各记一次读数,建议记录「空闲基线、加载完成后、静置一段时间后」三个时间点。静置后占用仍缓慢上涨,通常是缓存没有随请求释放,而不是权重变大。

nvidia-smi `--query-gpu`=memory.used,memory.total `--format`=csv -l 2
nvidia-smi `--query-compute-apps`=pid,process_name,used_memory `--format`=csv

非 NVIDIA 平台可以用 rocm-smi 或系统自带的显存面板;统一内存平台看的是系统内存与显存共享的总量。重点是同一命令在加载前后的差值,不必追求绝对值。

占用来源观察方式增长时机主要调整手段
模型权重加载完成后、无请求时的占用加载阶段一次性换更低比特量化、分片加载
KV 缓存请求变长、并发变多时的增量随上下文与并发增长缩短最大长度、限制并发、调整缓存分配
框架运行时开销加载后与空进程的差值启动时固定换后端、关闭不必要的预处理
批处理副本并发请求数增加时的占用随批大小增长降批大小与并发数

缩短上下文长度并观察峰值

这一步用来验证长上下文是不是主要增量。先把最大长度和批大小设成保守值,加载成功后再逐档放大。

model: NeoHorse-1
max_context_len: MAX_CTX    # 先给保守值,字段名按你的框架替换
max_batch_size: 1
max_concurrency: 1

测试时用同一条提示词,把输入长度按短、中、长分成几档,每档单独发一次请求,同时用 nvidia-smi -l 1 或框架自带的显存统计观察峰值。峰值至少记三个值:加载后基线、单请求峰值、请求结束后是否回落到基线附近。

NeoHorse-1 本地推理显存不够 / 先降上下文再换量化

如果短输入正常、长输入才爆,基本可以确认瓶颈在 KV 缓存,继续压上下文或限制并发即可;如果短输入也爆,说明权重本身占满了,直接进入量化那一步。

换成更低比特量化版本

量化版本通常会在文件名或配置里带位数标识,例如 8bit、4bit、Q4、Q5、int8、fp8 这类命名,具体以仓库提供的版本为准。位数越低,权重占用越小,但输出质量和速度能不能接受,需要自己判断。

# 示意,字段名按你的加载方式替换
quant_type: int4
load_in_4bit: true
dtype: auto

换量化后不要只看能不能加载,还要做一次连贯性检查:用同一段输入,看输出有没有明显重复、语句断裂、数字或代码片段被改写。偶发轻微退化通常可以接受;如果整段跑偏,就不建议为了省显存硬换。

需要留意的是,KV 缓存一般不会因为权重量化而同步变小,量化主要解决加载阶段的权重占用。长上下文仍是瓶颈的话,还是要回到上一步或继续调缓存策略。

调整推理后端的批处理和缓存策略

这一层改的是运行时怎么分配显存,适合权重已经能加载、但并发一上来就溢出的情况。常见可调项包括批大小、最大并发数和 KV 缓存开关。

NeoHorse-1 本地推理显存不够 / 先降上下文再换量化
max_batch_size: 1
max_concurrency: 1
kv_cache: on          # 单请求调试阶段可先关掉,观察纯权重占用
gpu_memory_utilization: 按保守值填写

验证顺序建议一项一项来:先只降批大小,用同一请求复测;再只降并发数;最后才考虑暂时关掉 KV 缓存观察纯权重占用。每改一项就记一次加载后基线和峰值,避免一次改多项之后无法判断是哪一项起作用。

关 KV 缓存这类做法只是临时定位手段,长文本生成会明显变慢甚至不可用,不适合当成长期方案。

用同一段任务复测稳定性

显存降下来不等于能正常用。准备一段固定输入,最好包含长段落和少量结构化内容,每次调整后都跑同一段。

重点记录三件事:输出长度是否明显短于调整前、是否出现截断或重复、错误日志里有没有 out of memory 之外的新报错(例如缓存分配失败、请求被中断)。

# 通用观察骨架
请求输入:固定文本 + 固定 max_tokens
记录:生成 token 数、结束原因、退出码、错误日志行
对比:调整前后是否都能完整跑完同一段任务

如果调整后能跑完、输出完整,只是速度慢了些,这个配置通常就是可用的;如果出现截断或中途退出,说明改动引入了新问题,需要回退该项再试。显存不够时,先降上下文、再换量化、最后调后端,是比较省事的排查顺序。