本地视频生成部署中,OOM(Out of Memory)几乎是最先撞上的墙。社区沉淀出的工程链路是“量化降本 → 权重按需卸载 → VAE 分片 → 参数约束 → 内存回收”,但新手最常收到的建议却是“降帧数、降分辨率”。本文以“14B 模型 + 12 GB 显存”这一典型错配场景为锚点,把显存占用拆成权重、激活、注意力、VAE 编解码、碎片与缓存五本账,逐维量化帧数、分辨率、步数、并发模型数四个旋钮的显存弹性与质量代价,提出“先砍并发、再砍分辨率、后砍帧数、最后动步数”的降维优先级,并给出可复现的显存预算表、分阶段加载流程与验证清单。核心判断是:降维不是等比缩放,而是沿“显存弹性系数”从高到低依次释放,任何跳过并发与分片直接降分辨率的做法,都是把可恢复的工程问题误当成模型能力问题。
一、问题的定义:OOM 不是“显存不够”,而是“账没算清”
先把场景钉死:一个参数量约 14B 的视频扩散模型(DiT 或 UNet 主干),部署在 12 GB 显存的消费级显卡上。按 FP16 计,仅权重就需要约 28 GB,这还没算文本编码器、VAE、激活值与注意力中间张量。也就是说,在 FP16 下这个组合在数学上就不可能成立,OOM 不是偶发故障,而是必然结果。新手收到的“降帧数、降分辨率”建议之所以流行,是因为它确实能让进程跑起来——但它回答的是“怎么不崩”,而不是“怎么还能用”。
这里需要区分三个常被混为一谈的概念。OOM(Out of Memory)指分配请求超过可用显存或显存池上限时驱动/运行时抛出的错误;显存峰值(peak memory)指一次前向或一次完整推理过程中瞬时占用的最大值;显存碎片(fragmentation)指空闲显存总量足够但连续块不足,导致大张量分配失败。三者的应对手段完全不同:峰值靠调度与分片,碎片靠分配器策略与回收,OOM 只是它们的共同症状。
笔者认为,绝大多数“降分辨率就好了”的经验,本质上是把峰值问题误判为容量问题。分辨率下降确实压低了激活张量,但它同时永久损失了输出信息量;而并发模型数、权重驻留策略这些“零质量损失”的旋钮,往往在建议里被完全忽略。
因此本文的分析主线是:把 OOM 当作一次显存预算审计,而不是一次参数调优。审计的对象是五类占用(权重、激活、注意力、VAE、碎片与缓存),审计的工具是每一维旋钮的“显存弹性系数”——即该维度变化 1 个单位时,峰值显存的变化率。只有先知道哪一维弹性最大、质量代价最小,才能回答“先降哪一维”。
为便于后续讨论,先给出本文使用的符号约定:设分辨率 H×W、帧数 F、批大小 B、去噪步数 S、同时驻留的模型数 M。视频扩散的潜空间张量形状通常为 [B, C, F', H', W'],其中 F'、H'、W' 是经 VAE 时空下采样后的潜尺寸(常见 8 倍空间下采样、4 倍时间下采样,具体因模型而异)。这个形状是后面所有估算的起点。
二、显存的五本账:把 12 GB 拆到每一项
2.1 权重账:量化是唯一能改变量级的杠杆
14B 参数在不同精度下的权重占用是硬约束:FP16 约 28 GB,BF16 同量级,INT8 约 14 GB,INT4 约 7 GB。可以看到,只有 INT4 才能让 14B 权重落进 12 GB 的预算内,且还要给激活和 VAE 留出空间。这就是社区链路把“量化降本”放在第一位的原因——它不是优化项,而是可行性前提。量化方法上,GPTQ、AWQ、SmoothQuant 以及近两年针对扩散模型提出的 SVDQuant、QServe 等方案,核心差异在于如何处理激活中的离群值(outlier)。本文评述:对视频扩散模型而言,量化误差会被时间维放大,单帧看起来可接受的色偏,在 49 帧连播时可能表现为闪烁,因此量化后必须做时序一致性检查,而不能只看单帧 PSNR。
2.2 激活账:与分辨率、帧数呈近似线性
激活值(activations)是前向过程中每层输出需要保留的中间结果。对 DiT 类结构,单层激活的元素数约为 B × F' × H' × W' × d(d 为隐藏维度),乘以层数再乘以同时保留的层数。关键结论是:激活随 F'×H'×W' 近似线性增长,而 H'、W' 又各自是原始分辨率的 1/8 左右,所以分辨率翻倍会让激活涨约 4 倍,帧数翻倍涨约 2 倍(时间下采样后)。这解释了为什么“降分辨率”对峰值显存如此有效——它是弹性系数最大的旋钮之一。
2.3 注意力账:序列长度的平方项
视频扩散的注意力通常在时空联合 token 上计算,序列长度 L ≈ F'×H'×W'。标准注意力的显存与 L² 成正比,这是最危险的一项。以 720×1280、49 帧、8 倍空间下采样、4 倍时间下采样估算,L 可达数万量级,L² 直接爆表。工程上的对策是 FlashAttention 系列、分块注意力(block-wise attention)、以及序列并行。本文评述:很多教程只教“降分辨率”,却没提“换注意力实现”,而后者是零质量损失的——FlashAttention 通过分块重计算把 O(L²) 的显存降到 O(L) 量级,属于应该最先尝试的手段。
2.4 VAE 账:编解码峰值常被低估
VAE 解码要把潜张量还原成像素张量,输出形状是 [B, 3, F, H, W]。以 720×1280、49 帧、FP16 计,单是输出张量就约 3×49×720×1280×2 ≈ 271 MB,而解码过程中的中间特征图往往是输出的数倍。更麻烦的是,VAE 解码常与主模型串行执行,峰值叠加。VAE 分片(tiling)正是为此设计:把空间或时间切成小块逐块解码再拼接,用时间换显存。本文评述:VAE 分片的质量风险在于块边界接缝,时间维分片尤其容易产生帧间跳变,实践中应优先空间分片、保留重叠区域(overlap)再做羽化融合。
2.5 碎片与缓存账:看不见的第三本账
PyTorch 的 CUDA 缓存分配器会保留已释放的块以备复用,这提高了速度却抬高了常驻占用。此外,文本编码器(如 T5 类)在提示词编码后本可卸载,但很多流水线默认让它常驻。碎片问题的典型表现是:nvidia-smi 显示还有 2 GB 空闲,进程却报 OOM。对策包括设置 PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True、在阶段切换时调用 torch.cuda.empty_cache()、以及避免频繁变形状分配。本文评述:碎片是“工程债”,它不会因为降分辨率而消失,反而可能因为张量形状变化更频繁而加剧,因此回收策略必须与降维策略同步设计。
| 占用项 | FP16 估算 | INT4 权重后 | 可压缩手段 |
|---|---|---|---|
| 主模型权重 | ≈28 GB | ≈7 GB | INT4 量化、按需卸载 |
| 文本编码器 | ≈4–9 GB | 编码后卸载 | CPU 卸载、分阶段加载 |
| 激活值 | 随分辨率/帧数线性 | 同左 | 梯度检查点、降分辨率/帧数 |
| 注意力中间量 | O(L²) | 同左 | FlashAttention、分块注意力 |
| VAE 编解码 | 数百 MB 起 | 同左 | VAE 分片、CPU 解码 |
| 缓存与碎片 | 1–3 GB | 同左 | expandable_segments、empty_cache |
把表 1 加总可以看出:即便 INT4 量化后权重降到 7 GB,文本编码器、激活、注意力、VAE 与碎片仍会轻易吃掉剩余 5 GB。这意味着单靠量化不足以让 14B 在 12 GB 上跑起来,必须叠加“分阶段加载 + 注意力优化 + VAE 分片”。这也从预算角度证伪了“只降分辨率就行”的朴素经验:分辨率只影响激活与注意力两项,权重和编码器这两块大头纹丝不动。
三、四个旋钮的显存弹性系数与质量代价
本节逐一量化四个旋钮。所谓“显存弹性系数”,本文定义为 E = (Δ峰值/峰值) / (Δ参数/参数),即参数相对变化引起的峰值显存相对变化。弹性越大,调它越“划算”;但还要叠加“质量代价”,即该参数对输出可用性的影响。两个维度共同决定优先级。
3.1 同时加载的模型数 M:弹性最高、质量代价为零
典型视频流水线包含文本编码器、主扩散模型、VAE 解码器三段,若全部常驻,显存是三者之和。分阶段加载(先编码文本→卸载→加载主模型去噪→卸载→加载 VAE 解码)可以把峰值从“和”降到“最大值”。这一维的弹性接近 1(省下的就是整块模型),质量代价严格为零——输出与全常驻完全一致,只是多了几次 PCIe 传输和加载延迟。本文评述:在 12 GB 这种紧预算下,M 应该是第一个被压到 1 的旋钮,任何在 M>1 时就去降分辨率的做法都是本末倒置。
3.2 分辨率 H×W:弹性高、质量代价中等且可感知
分辨率同时进入激活(线性于面积)和注意力(平方于 token 数)两项,弹性系数在 1–2 之间,是降峰值最有效的手段之一。但质量代价明确:分辨率直接决定细节上限,720p 降到 480p 再降到 360p,人脸、文字、纹理依次崩坏。更隐蔽的是,分辨率下降会改变模型的工作点——许多视频模型在训练时使用固定分辨率桶(bucket),偏离训练分布会引入构图异常。本文评述:分辨率应作为“第二顺位”,且优先采用“保持短边、裁切长边”而非等比缩小,以尽量贴近训练分布。
3.3 帧数 F:弹性中等、质量代价体现在运动连续性
帧数经时间下采样后对激活的贡献约为线性(系数 1/4 左右),弹性低于分辨率。质量代价不是“画质变差”而是“时长变短、运动断裂”:从 49 帧降到 25 帧,单段视频时长腰斩,长镜头叙事被切断。本文评述:帧数与分辨率的关键区别在于,帧数可以通过“分段生成 + 首尾帧衔接”部分补偿,而分辨率损失不可逆。因此在必须二选一时,优先保分辨率、降帧数并配合分段续写,往往比反过来更可接受。
3.4 去噪步数 S:弹性最低、质量代价呈非线性
步数影响的是“迭代次数”而非“单次峰值”——每一步的显存占用基本相同,降步数几乎不降峰值,只降总耗时。换句话说,步数对 OOM 基本无效。它的质量代价却呈非线性:从 50 步降到 30 步通常肉眼难辨,降到 15 步开始出现结构崩坏,降到 8 步以下需要蒸馏模型(如 LCM、Turbo 系列)支撑。本文评述:把“降步数”当作 OOM 对策是常见误解,它解决的是速度问题不是显存问题;但在显存已够、只是太慢的场景下,步数是性价比最高的旋钮。
| 旋钮 | 显存弹性 | 质量代价 | 可逆性 | 建议顺位 |
|---|---|---|---|---|
| 并发模型数 M | 高(≈1) | 无 | 完全可逆 | 1 |
| 分辨率 H×W | 高(1–2) | 中,细节不可逆损失 | 部分可逆 | 2 |
| 帧数 F | 中(≈0.25–0.5) | 中,运动断裂可补偿 | 可通过分段续写补偿 | 3 |
| 步数 S | 极低(≈0) | 非线性,低步崩坏 | 可逆 | 4(仅速度场景) |
表 2 给出的顺位是本文的核心主张。需要强调,这个顺位的前提是“目标是让 14B 在 12 GB 上产出可用视频”,而非“最快跑通”。若目标只是跑通,那么先降分辨率确实最快见效——但那就掉进了标题所说的陷阱:把“能跑”降成“不能用”。
四、降维优先级:一条可执行的决策链
把前面的分析收束成一条可操作的决策链,按“零代价 → 低代价 → 中代价 → 高代价”顺序执行,每步之后用显存探针验证,不达标再进下一步。
第 0 步:量化与注意力实现(不动输出语义)
先把主模型权重压到 INT4(GPTQ/AWQ/SVDQuant 等),文本编码器按需加载或 CPU 卸载,注意力切换到 FlashAttention 或分块实现。这一步的目标是把“权重 + 注意力”这两块最大占用压下来,且理论上不改变输出分布(量化误差需实测验证)。
第 1 步:并发模型数压到 1(零质量代价)
改流水线为分阶段:文本编码 → 卸载编码器 → 主模型去噪 → 卸载主模型 → VAE 解码。用 torch.cuda.empty_cache() 在阶段间回收,并开启 expandable_segments 抑制碎片。此步之后若峰值已低于 12 GB,直接结束,不要动分辨率。
第 2 步:VAE 分片(低质量代价)
若 VAE 解码阶段仍 OOM,启用空间分片 + 重叠羽化,必要时把 VAE 放到 CPU 解码(速度换显存)。此步只影响解码阶段峰值,不影响扩散过程。
第 3 步:分辨率(中质量代价,最后才动)
前三步仍不够时,才降分辨率,且优先“短边保底 + 长边裁切”,并记录降到的档位,作为该硬件的“质量下限”。
第 4 步:帧数(配合分段续写)
分辨率已到下限仍 OOM,再降帧数,并用首尾帧条件做分段生成,把短片段拼回长视频,尽量保住叙事长度。
# 显存探针:在关键阶段打印峰值,验证每一步是否生效
import torch
def probe(tag):
torch.cuda.synchronize()
alloc = torch.cuda.memory_allocated() / 1024**3
peak = torch.cuda.max_memory_allocated() / 1024**3
print(f"[{tag}] alloc={alloc:.2f}GB peak={peak:.2f}GB")
torch.cuda.reset_peak_memory_stats()
# 分阶段流水线骨架(示意)
probe("start")
text_emb = encode_text(prompt) # 文本编码
unload(text_encoder); torch.cuda.empty_cache(); probe("after_text")
latent = denoise(model_int4, text_emb) # 主模型去噪
unload(model_int4); torch.cuda.empty_cache(); probe("after_denoise")
video = vae_decode_tiled(latent) # VAE 分片解码
probe("after_vae")
这条链的关键在于每一步都可验证、可回退。探针打印的 peak 是判断“这一步是否真的省了显存”的唯一依据,而不是凭感觉。本文评述:工程上最常见的失败不是选错旋钮,而是改了参数却没验证,误以为生效,结果在另一个阶段继续 OOM。
五、工程链路落地:量化、卸载、分片与回收
5.1 量化降本:选型与验证
量化不是“压完就完”。对视频模型,必须验证三件事:单帧画质(PSNR/SSIM 或人眼)、时序一致性(相邻帧差分是否异常)、以及提示词遵循度是否漂移。公开资料中,SVDQuant 等工作针对扩散模型的激活离群值做了专门处理,QServe 则从系统层面优化低比特推理。本文评述:量化位宽不是越低越好,INT4 是当前 12 GB 跑 14B 的现实下限,INT3 及以下在视频任务上的时序稳定性尚缺充分公开验证,不建议生产使用。
5.2 权重按需卸载:CPU 与 GPU 的舞蹈
卸载(offload)的本质是把暂时不用的权重放到 CPU 内存,用时再传回。代价是 PCIe 带宽成为瓶颈,速度可能下降数倍。工程要点是“卸载粒度”:整模型卸载简单但传输量大,分层卸载精细但调度复杂。本文评述:在 12 GB 场景下,卸载是让 14B“能跑”的必要手段,但应尽量只卸载编码器和 VAE,主模型常驻,避免去噪循环中反复搬运导致速度不可用。
5.3 参数约束与内存回收
参数约束指给运行时设定显存上限、限制并发请求、固定张量形状以减少碎片。内存回收包括主动 empty_cache、复用缓冲区、以及避免在循环中创建新张量。本文评述:这些手段单独看都是“小优化”,但在紧预算下它们的总和可能决定成败——碎片省下的 1–2 GB,往往就是分辨率能否保住一档的关键。
- Nunchaku / SVDQuant 官方仓库——4-bit 扩散模型推理的工程实现。
- FlashAttention 官方仓库——注意力显存优化的基础实现。
- PyTorch CUDA 内存管理文档——缓存分配器与 expandable_segments 说明。
- Diffusers 显存优化指南——offload、attention slicing、VAE tiling 的官方教程。
六、对比与局限:哪些场景下“降维”是错的
前文的顺位并非放之四海皆准。至少有三类场景需要反向操作。第一,批量离线生成:若吞吐优先于单条质量,降分辨率 + 降步数换并发是合理的,因为总输出量才是目标。第二,训练/微调:显存瓶颈在优化器状态与梯度,降分辨率只能缓解激活,必须配合梯度检查点、LoRA、ZeRO 等,此时“降维”不是主矛盾。第三,高分辨率修复流程:先生成低分辨率再超分,本质上是把分辨率旋钮拆成两段,质量损失可能小于一次性降分辨率,但流程复杂度上升。
还需要正视本文分析的局限。其一,表 1、表 2 的数值是基于公开模型结构参数的模拟估算,不同模型(DiT 与 UNet、不同下采样倍率、不同注意力实现)差异显著,读者应以自己环境的探针实测为准。其二,量化对时序一致性的影响缺乏统一评测基准,现有结论多为单模型、单数据集的报告,外推需谨慎。其三,碎片行为高度依赖驱动版本与分配器实现,跨平台可复现性有限。本文评述:承认这些局限,恰恰是反对“一招降分辨率通吃”的理由——正因为变量多,才更需要按弹性排序、逐步验证,而不是拍脑袋选一个最显眼的旋钮。
七、结论与展望
回到标题的问题:14B 模型在 12 GB 卡上 OOM,先降哪一维?本文的答案是——先降“同时加载的模型数”,再降分辨率,后降帧数,步数基本不解决 OOM。这条顺位的依据不是经验口诀,而是显存弹性系数与质量代价的联合排序:并发模型数弹性最高且零代价,分辨率弹性高但损失不可逆,帧数弹性中等且可分段补偿,步数弹性近零。把这条链走完仍不够,才说明硬件确实越界,此时应考虑换卡或换更小的模型,而不是继续在“能用”的边缘试探。
展望来看,三个方向值得关注:一是低比特量化与注意力优化的协同,把“零代价”空间继续做大;二是分片与并行的自动化调度,让运行时根据探针动态选择降维策略,而非人工试错;三是面向视频的显存-质量联合基准,目前社区缺少统一评测,导致经验难以迁移。本文评述:OOM 治理的终局不是“记住几个参数”,而是建立一套可观测、可回退的显存预算方法论——这才是从“能跑”走向“能用”的分水岭。
- Li M, et al. SVDQuant: Absorbing Outliers by Low-Rank Components for 4-Bit Diffusion Models. 2024.
- Lin Y, et al. QServe: W4A8KV4 Quantization and System Co-design for Efficient LLM Serving. MLSys, 2025.
- Dao T. FlashAttention-2: Faster Attention with Better Parallelism and Work Partitioning. ICLR, 2024.
- Peebles W, Xie S. Scalable Diffusion Models with Transformers (DiT). ICCV, 2023.
- Blattmann A, et al. Stable Video Diffusion: Scaling Latent Video Diffusion Models. 2023.
- Frans K, et al. Scaling Laws for Diffusion Transformers. 2024.
- Frantar E, et al. GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers. ICLR, 2023.
- Lin J, et al. AWQ: Activation-aware Weight Quantization for On-Device LLM Compression. MLSys, 2024.
说明:本文涉及显存数值为基于公开模型结构参数的模拟估算,未使用自建数据集;量化时序一致性相关结论参考上述公开文献的单模型报告,外推需谨慎。
文章声明:本文内容仅为作者学习、思考、经验、笔记的总结,仅供技术交流与参考。文中观点仅代表笔者个人思辨,不构成任何学术建议、商业建议或专业建议。所有数据来源已标注,引用时请以原始文献为准。

