SeFi-Image 装到本机跑图,先按显存定分辨率和采样步数

文章导读
装到本机之后第一张图跑不出来,通常不是模型本身坏了,而是分辨率、精度(dtype)、采样步数三项都按默认值给满了:分辨率决定显存占用的基数,精度决定同一张图要用多少显存装权重和中间张量,采样步数决定推理阶段要重复多少次。三项同时改,就分不清是哪一项压垮了显存。稳妥的做法是先固定一组能跑通的最小参数,拿到一张成功的图,再单项往上加。
📋 目录
  1. A 在本机确认依赖与权重目录能被读到
  2. B 用最低分辨率跑通第一次推理
  3. C 读显存峰值定位卡在哪一阶段
  4. D 按显存余量依次调分辨率、精度、采样步数
  5. E 固化一组稳定参数并复现
A A

装到本机之后第一张图跑不出来,通常不是模型本身坏了,而是分辨率、精度(dtype)、采样步数三项都按默认值给满了:分辨率决定显存占用的基数,精度决定同一张图要用多少显存装权重和中间张量,采样步数决定推理阶段要重复多少次。三项同时改,就分不清是哪一项压垮了显存。稳妥的做法是先固定一组能跑通的最小参数,拿到一张成功的图,再单项往上加。

本机跑 SeFi-Image 的可行路径:先把依赖和权重路径确认到能加载,再用最低分辨率、单张、低步数跑通第一张图作为基线;随后用 nvidia-smi 或 torch 峰值统计确认卡在加载、推理还是解码阶段,按「先分辨率、再精度、最后步数」的顺序单项调整,每次只改一项并记录峰值。适用场景是单机单卡的本地出图;边界是显存不足以外的卡死(路径错、依赖没装、驱动不匹配)不算在内,需要先排除环境问题。

在本机确认依赖与权重目录能被读到

先确认程序真的读到了依赖和权重,否则后面所有分辨率调整都是在给环境问题背锅。依赖清单按脚本实际的 import 逐项核对:Python 解释器、CUDA 运行时与 PyTorch 的匹配关系、图像处理库(Pillow、numpy)、可选的加速组件(accelerate、xformers 之类),以及 safetensors 读取库。判断标准不是版本号,而是 python -c "import torch; print(torch.cuda.is_available())" 能返回 True,并且脚本能在 `--device` cuda:0 下启动而不回落到 CPU。

权重目录结构通常长这样,字段名按你手上的仓库替换:

models/
└── sefi-image/
    ├── model_index.json
    ├── unet/
    │   └── diffusion_pytorch_model.safetensors
    ├── text_encoder/
    ├── vae/
    └── tokenizer/

启动时用绝对路径指向 sefi-image 这一层,不要指到 unet 子目录、也不要直接指 safetensors 文件本身,这是最常见的加载失败来源。一次成功加载的日志通常有这些特征:先打印配置或 model_index 被读取,然后逐个列出子权重文件正在加载(形如 Loading checkpoint shards 或 Loading weights),接着打印最终 device 与 dtype,最后进入推理流程且没有 Traceback。如果日志停在某个权重文件名上不再前进,先检查该文件是否完整、路径是否可读,不要继续调分辨率。

用最低分辨率跑通第一次推理

基线要足够低:单张、batch size 取 1、分辨率降到显存明显吃得下的档位、采样步数先给到能看出轮廓的量(例如十步上下),精度先用 fp16 或脚本默认的半精度选项。这个组合通常出不了好图,但它能出图,就有了对照物。

SeFi-Image 装到本机跑图,先按显存定分辨率和采样步数
python scripts/txt2img.py \
  `--prompt` "a cat sitting on a wooden table" \
  `--width` 512 `--height` 512 \
  `--steps` 10 `--batch` 1 \
  `--dtype` fp16 \
  `--device` cuda:0 \
  `--seed` 1234 \
  `--outdir` ./out

参数名按实际脚本字段替换,不要照抄。判断出图成功的依据有三条:进程退出码为 0;日志末尾打印了保存路径或耗时;输出目录里确实出现了新的图片文件,能打开且不是全黑或全灰。把这张图和它使用的参数一起记下来,它就是后面所有调整的参照点。

读显存峰值定位卡在哪一阶段

开两个终端,一个跑推理,一个盯显存。通用监控方式是 nvidia-smi:watch -n 0.5 nvidia-smi 看整体占用,或 nvidia-smi `--query-gpu`=memory.used,memory.total `--format`=csv -l 0.5 打时间序列。想看进程内部的真实峰值,在脚本里加 torch.cuda.reset_peak_memory_stats() 与 torch.cuda.max_memory_allocated(),在「加载完成、采样循环中、解码完成」三个位置各打一次。

三个阶段的峰值时机不一样:加载阶段是一次性抬升,权重进显存后占用基本稳住;推理阶段随采样步小幅波动,峰值与分辨率、batch size 正相关;解码阶段(把潜变量还原成图)往往在采样循环结束后再抬一次,高分辨率下这一下经常是最后一根稻草。超限时的报错原文特征通常是 CUDA out of memory. Tried to allocate ... 或 torch.cuda.OutOfMemoryError,括号里会写明当前显卡和已占用、总容量。报错栈的位置能反推阶段:出现在权重加载时是加载阶段,出现在采样循环里是推理阶段,出现在解码或保存前后就是解码阶段。

按显存余量依次调分辨率、精度、采样步数

顺序是分辨率 → 精度 → 采样步数。分辨率对显存接近平方关系,动一次效果最明显;精度更像一道开关(fp32 换 fp16/bf16,或打开 attention slicing、分块解码),改一次占用会台阶式变化;采样步数与显存近似线性,但它恰好是你感知最强的一项,一上手就砍它,结果是花了时间还是爆显存。下面这张表按标称显存分档给起点,实际可用余量要以 nvidia-smi 读数减去系统与桌面占用后再判断。

SeFi-Image 装到本机跑图,先按显存定分辨率和采样步数
显存档位第一步:分辨率第二步:精度第三步:步数验证方式
8GB 及以下512×512 起步,先保证能出图fp16,必要时开切片或分块解码保持低位,够看轮廓即可跑完后留出余量
12–16GB768 起步,单项往上探fp16 / bf16逐步加到二十步上下每加一档看峰值
24GB 及以上1024 起步保持半精度按画质需求给确认解码阶段不触顶

参数片段按脚本实际字段名替换,注意有的仓库叫 `--precision`、有的是 `--half`、步数也可能叫 `--sampler`_steps:

width: 512
height: 512
dtype: fp16          # 或 precision: fp16 / half: true
steps: 10            # 或 sampler_steps
batch_size: 1
seed: 1234

每次只改一项,按下面这张表记一行,改完先把这张图跑出来再动下一项。两轮之间如果同时改了分辨率和精度,峰值变化就没法归因。

轮次本次改动项分辨率精度步数峰值显存是否出图
1基线,不改512×512fp1610
2只提分辨率 fp1610
3只换精度 10
4只加步数

固化一组稳定参数并复现

出图稳定后,把参数落到一份文件(yaml / json 或一段启动脚本),不要留在终端历史里。固定随机种子(`--seed` 或等效字段),同时记下会一起影响结果的项:dtype、调度器或采样器、步数、分辨率、batch size、是否有 LoRA 及其权重目录。

sefi_image:
  prompt: "a cat sitting on a wooden table"
  seed: 1234
  width: 512
  height: 512
  steps: 10
  dtype: fp16
  batch_size: 1

复现验证的方法很直接:用同一份配置、同一台机器重跑一次,比较输出的尺寸、种子和图像内容。两次肉眼一致,这组参数就可以固定下来;如果出现细微差异,通常是 cudnn benchmark、部分加速算子或分块解码带来的非确定性,可以先关掉加速项、打开确定性选项再比一次,确认差异来源,而不是回头继续改分辨率。换机器或换驱动之后,这组参数需要按新机器的实际显存读数重新确认一遍。