在本地跑 Muse Image,最常被问到的不是怎么装,而是这块显卡到底够不够。显存需求没有固定数,它取决于你加载的权重大小、精度设置、输出分辨率和批次数。先把这几个变量定下来,才能判断手里的 GPU 是能直接跑,还是需要先做减载。
判断显存是否够用的核心动作,是把权重占用和推理激活分开估算:先看模型文件大小或参数量,按 FP16 约每十亿参数 2GB 计算权重底线,再为激活值和缓冲区预留一倍左右余量。建议用最小分辨率和 batch=1 做一次推理,以 torch.cuda.max_memory_allocated 或 nvidia-smi 观测到的峰值为准。显存不够时优先降分辨率、降精度或分批生成,而不是依赖 swap 兜底。
这里说的预留一倍余量,不是一个精确公式,而是一种保守规划方式。Muse 这类基于 Transformer 的图像生成模型,推理时除了模型权重,还要保存中间激活值和 KV cache,分辨率提高会让 token 序列变长,激活占用往往成倍上涨。先按权重乘 2 估算下限,比直接看权重大小更接近真实申请量。
先估算权重和激活的占用
建议先确认你拿到的权重格式和参数量。按通用换算,FP32 每十亿参数约 4GB,FP16 每十亿参数约 2GB,INT8 每十亿参数约 1GB。如果权重文件来自社区分享,文件大小可以直接参考;如果包含优化器状态或分片,需要先剔除多余部分。
| 加载精度 | 每十亿参数权重估算 |
|---|---|
| FP32 | 约 4GB |
| FP16 / BF16 | 约 2GB |
| INT8 | 约 1GB |
上表只是权重本身。完整推理时,建议在权重估算基础上再预留 1.5 到 2 倍空间,用于激活值、临时缓冲区和运行时分配。如果 GPU 总显存明显低于这个估算值,就有必要降低精度或分辨率,再用实测确认。
用最小成本做一次显存实测
估算不能替代实际观察。写一个最简单的加载和单次生成脚本,用最小分辨率、batch=1,观测峰值显存。下面是一个通用骨架,加载模型部分要替换成你部署项目实际所用的方式。
import torch
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print('设备:', device)
if device.type == 'cuda':
free, total = torch.cuda.mem_get_info(0)
print('GPU 总量: {:.2f} GB, 空闲: {:.2f} GB'.format(
total / 1024**3, free / 1024**3))
# 替换成你的模型加载代码
# model = load_model(...)
# model.to(device)
with torch.no_grad():
# 用最低分辨率、batch=1 生成一次
# output = model.sample(...)
torch.cuda.synchronize()
peak = torch.cuda.max_memory_allocated() / 1024**3
print('本次生成峰值显存: {:.2f} GB'.format(peak))运行这个骨架,得到的就是当前精度和分辨率下的真实显存占用。如果峰值已经接近 GPU 总量,后续提高分辨率或并发生成都会爆显存。建议把这次输出的峰值记录为你的“显存下限”。
按照显存余量做规划
拿到峰值之后,按照下面的优先级做取舍,而不是一开始就换卡。
- 先降分辨率:分辨率直接决定 token 数量,对显存影响最直接。
- 再换低精度:如果方案支持,从 FP16 降到 INT8 或 4bit 能省出一块空间,但可能改变输出风格。
- 最后考虑 CPU offload:把部分层搬到内存运行,显存压力减小,但生成变慢。
- swap 和虚拟内存只能防止进程崩溃,不能作为提速方案。
如果是想买卡或调整环境,不要只看单次峰值。同一张卡,不同精度、不同分辨率下表现差别很大。等到实际操作时,先按峰值乘以期望余量来选,比如你希望还能再开一个别的任务,就留出对应空闲。
常见问题
为什么按权重算只有 2GB,实际跑起来却占了 8GB?
因为推理时的激活值和 KV cache 才是大头,尤其图像模型在高分辨率下 token 数量会很快膨胀,显存占用不是线性增加的。权重估算只能作为地板,不能作为预期占用。
量化之后生成效果变差怎么办?
量化会改变模型内部数值分布,常见表现是颜色偏灰、结构崩坏。可以先保持量化,降低分辨率再试;如果仍然不行,只能回到更高精度,并接受显存占用增加。
批大小设为 1 还是调低分辨率?
在显存不足时,优先调低分辨率,因为它减少的是整条 token 序列长度;批大小设为 1 是最后一道防线,通常先降分辨率再调 batch。