UniWorld-View 在本地一跑就爆显存,比较省事的处理顺序是:先不要动精度,也不要急着换卡,而是把「分辨率」和「帧数」这两个维度各自吃掉多少显存量出来。有了这两组数字,你才能判断该降哪个、能降到哪一档,而不是每次改参数靠猜。下面是一套可以在单机单卡上复现的测量流程,外加一张需要你自己填的记录表。
判断方向:先在能跑通的最小配置上量一次峰值显存作为基准,再固定其余参数、只降帧数记录一组峰值,然后把帧数固定在计划档位、只降分辨率记录第二组,两组换算成同一横轴画在一张图上比斜率。适用场景是单机单卡、显存吃紧的推理任务;操作是用 nvidia-smi 轮询采样;验证是同配置连续跑几次看波动;风险边界是采样间隔过粗会漏掉瞬时峰值,监控脚本本身也占少量显存,结论需结合本机环境确认。
先量一次当前配置的峰值显存
基准数字决定了后面所有对比是否成立。挑一个当前能跑通(哪怕很慢)的配置,把各项参数先记下来,然后单独开一个终端做轮询采样,推理开始前启动、结束后停掉。
下面的骨架按 0.5 秒间隔采一次,输出 CSV,方便后面直接做极值统计。注意列号跟 `--query-gpu` 里字段的顺序绑定,改字段就要同步改后面的 awk。
# gpu_watch.sh,用之前先清空旧日志
: > gpu_mem.log
while true; do
nvidia-smi `--query-gpu`=timestamp,memory.used,memory.total,utilization.gpu \
`--format`=csv,noheader,nounits >> gpu_mem.log
sleep 0.5
done
# 另开一个终端,跑完推理后取峰值($2 对应 memory.used)
awk -F', *' '{if ($2+0 > max) max=$2+0} END {print max}' gpu_mem.log间隔怎么定:0.5 秒通常够用,但可能漏掉很短的峰值。如果你发现轮询算出的最大值和手动盯 nvidia-smi 看到的数字差得明显,就换成 0.2 秒重测一遍。监控本身会占用少量显存和 CPU,在各档之间是同等的,不影响横向对比,但不要在监控之外再叠加其他吃显存的程序。
每次测量至少记录这些字段,后面三节都用同一张表往下填:配置名、分辨率(宽×高)、帧数、精度(dtype)、batch、采样间隔、峰值显存(MiB)、总显存、是否 OOM、备注(模型版本、驱动版本、同机其他进程)。
固定其余参数,只降帧数看峰值变化
这一节只回答一个问题:帧数每降一档,峰值显存会跟着降多少。所以除帧数外,其他项必须全程锁死,否则测出来的差值没有意义。
| 锁定项 | 本节取值 | 说明 |
|---|---|---|
| 分辨率 | 基准配置值 | 全程不变 |
| 精度 / dtype | 基准配置值 | 不要中途切 fp16/fp32 |
| batch | 基准配置值 | 保持为 1 更好比较 |
| 模型与权重 | 同一份 | 换权重等于换实验 |
| 采样间隔 | 统一 | 两节之间也不要改 |
| 后台进程 | 尽量一致 | 关掉浏览器、其他占显存任务 |
帧数从大到小往下扫,每档跑一次、填一行:帧数=N | 峰值=___ MiB | 是否 OOM | 耗时。如果帧数已经降到很低仍然爆显存,说明瓶颈不在帧数维度,别再往下试,直接进入下一节。
再单独降分辨率,形成两组对照数据
实验顺序建议是:先把帧数扫描做完,从中选定一个你打算长期使用的帧数,把它固定住,再扫分辨率。这样第二组的起点可以和第一组的某一档重合,作为一个交叉校验点——同一配置两次测量如果差得比较多,说明采样或环境不稳定,先把这个问题解决再继续。
| 档位 | 分辨率 | 帧数 | 帧数固定后的峰值 | 是否 OOM |
|---|---|---|---|---|
| R1 | 最高计划分辨率 | 固定值 | 待填 | 待填 |
| R2 | 次一档 | 固定值 | 待填 | 待填 |
| R3 | 再降一档 | 固定值 | 待填 | 待填 |
两张表要能画进同一张图,横轴就得用同一个量纲。建议横轴统一换算成「总像素帧数」= 宽 × 高 × 帧数,纵轴是峰值显存(MiB),把帧数组和分辨率组的点都画上去,看各自那段曲线的坡度。哪一段更陡,说明该维度对显存的边际影响更大。但最终取舍不只看显存:分辨率影响画面细节,帧数影响时长,哪个更能妥协要按你的用途定。
选一档留出可观测余量的配置
日常档位不要卡在临界点上。判断余量的做法是:挑出候选配置,连续跑 5 次左右,记录每次峰值,看最大值和最小值之间差多少。默认档位要设在这个历史最高值之上再留一段空间,别正好压线;留多少没有通用数字,需要结合本机驱动、框架的缓存策略和常驻进程一起确认。另外总显存要先扣掉桌面环境、浏览器等常驻占用,剩下的才是你能用的量。
选定后写进启动脚本,用环境变量做默认值、允许临时覆盖,这样换档不用改脚本:
#!/usr/bin/env bash
set -euo pipefail
# 默认档位:按上面的实测表选出的留余量配置
RES=${UW_RES:-640x360}
FRAMES=${UW_FRAMES:-16}
# 该变量在不同 PyTorch 版本上的支持情况需要先确认
export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True
python run_infer.py `--resolution` ${RES} `--num-frames` ${FRAMES}验证方式:用这个脚本跑同一档配置,再开一次轮询,确认峰值落在你预期的区间内、且没有贴着上限。换机器、换驱动、换模型权重之后,这张表要重测一遍,旧结论不要直接沿用。