feat: fit the 18B model on a 24 GB GPU + 64 GB RAM box (staged T5, eager FP8, FP8-only deepcopy) - #20
Open
yangohuang wants to merge 3 commits into
Open
Conversation
umT5-xxl (~11 GB) stays resident for the whole run even though every prompt is known upfront. On 64 GB-RAM hosts this collides with the 18B DiT (~36 GB bf16) during loading and the process gets OOM-killed. Encode all prompts (including edit_prompt) in a staging pass, free the T5 encoder, then load the DiT with low_cpu_mem_usage=True. Peak host memory drops by ~11 GB; outputs are unchanged for every input json.
WanBlockOffloadManager deep-copies blocks[0] for its staging buffers. If fp8 weights were materialized with fp16_weight_storage='discard' before enable_block_offload() is called, __deepcopy__ raises RuntimeError because no fp16 source remains, even though the fp8 buffers are sufficient to reconstruct the module. Rebuild from a zero placeholder in that case and clone the fp8 buffers (the existing clone path below already handles them), then drop the placeholder copies.
…fload With block offloading, weights live on the host and only fp8 buffers need to travel to the GPU staging blocks each step. Keeping the bf16 originals (~36 GB for the 18B DiT) on the host until lazy first-forward quantization leaves a long window where VAE/CLIP/wav2vec loads push a 64 GB-RAM machine into the OOM killer. Quantize block by block on GPU right after the DiT loads, discarding each bf16 copy immediately: host steady-state drops to ~18 GB and the per-step H2D copy volume is halved. Gated on --block_offload so the datacenter path (no offload) keeps its existing lazy behavior. Requires the FP8-only __deepcopy__ path from the previous commit, since enable_block_offload() deep-copies blocks[0] after the bf16 weights are gone.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
The README's RTX 4090/5090 command currently cannot run on a 24 GB GPU with a 64 GB-RAM host:
--offload_cachemoves the pressure to the host, where the bf16 DiT (18B ≈ 36 GB) cannot co-reside with umT5-xxl (~11 GB) — the kernel OOM killer terminates the process during model loading.Related reports: #18, #12. Builds on the same test setup as #19 (independent, both merge cleanly).
Changes
Three commits, each self-contained; the datacenter (no-offload) path is untouched:
edit_prompt) in a staging pass and release the T5 encoder before loading the DiT; also load the DiT withlow_cpu_mem_usage=True. Peak host RAM drops by ~11 GB. Outputs are unchanged for every input json.__deepcopy__forFP8Linear—WanBlockOffloadManagerdeep-copiesblocks[0]for its staging buffers; if fp8 weights were materialized withfp16_weight_storage='discard'beforeenable_block_offload(), this currently raisesRuntimeError: FP8Linear cannot be deep-copied without an FP16 weight source. Reconstruct from a placeholder and clone the fp8 buffers instead. This is a latent bug reachable by any API user today, and a prerequisite for change 3.--fp8_gemm --block_offload— quantize block-by-block on GPU right after the DiT loads, discarding each bf16 copy immediately. Host steady-state drops from ~36 GB to ~18 GB before the VAE/CLIP/wav2vec loads, and the per-step H2D copy volume of the offload double-buffer is halved. Gated on--block_offload, so the H100/H200 path keeps its existing lazy behavior.Measured (RTX 4090 24 GB, 62 GB RAM)
Command:
--size 256*416 --fps 24 --fp8_gemm --fp8_kv_cache --block_offload --t5_cpuNot real-time, but it turns "cannot run at all" into a working offline-generation path on a common consumer box.
中文说明
动机:README 的 RTX 4090/5090 命令在 24G 显存 + 64G 内存的机器上实际无法运行——416×720 下仅 KV cache 就需约 20G 显存(3 个去噪步 × 40 层独立缓存);改用
--offload_cache后,主机又无法同时容纳 bf16 DiT(18B ≈ 36G)与 umT5-xxl(约 11G),进程在加载阶段就会被内核 OOM killer 杀掉。相关:#18、#12。与 #19 相互独立、可分别合并。三项改动(均不影响 H100/H200 原有路径):
edit_prompt)预编码并释放 T5,同时 DiT 改用low_cpu_mem_usage=True加载。主机内存峰值降低约 11G,任意输入 json 的输出完全不变;FP8Linear.__deepcopy__支持纯 FP8 源:offload manager 初始化时会 deepcopyblocks[0]作为暂存缓冲,bf16 已丢弃时现有代码会抛RuntimeError——改为从占位结构重建并克隆 fp8 buffer。这是一个当前 API 即可触发的潜伏 bug,也是改动 3 的前置条件;--fp8_gemm --block_offload下的即时 FP8 量化:DiT 加载后立即逐 block 在 GPU 上量化并丢弃 bf16 原权重,主机常驻内存 36G → 约 18G,同时 offload 双缓冲的每步 H2D 拷贝量减半。已用--block_offload门控,数据中心路径保持原有惰性行为。实测(RTX 4090 24G + 62G 内存):256×416 @ 24fps、3 步去噪,38 秒成片完整生成;稳态 SDPA 约 37.7s / SageAttention 约 31.9s 每 1.33 秒视频(RTF≈28 / 24);GPU 峰值约 13G,主机峰值约 30G。改动前同配置在加载阶段即被 OOM killer 终止。
虽非实时,但把消费级主机上的"完全跑不起来"变成了可用的离线出片路径。