Repository navigation
fix(vae): honor the loaded model compute device - #10145
wunianze666-netizen wants to merge 4 commits into
Conversation
Route VAE tensors and reference encode estimates to the loaded VAE device. Recognize CPU allocator failures in the existing tiled retry.
Pfannkuchensack
left a comment
There was a problem hiding this comment.
Thanks, this fixes every path listed in #10014. Encode, tile decision and estimate all follow compute_device, and results are moved on to where downstream expects them. Reverting any listed path makes a test fail, also on a CPU-only box. No blockers; checked on CPU with a simulated accelerator session, not on real hardware.
Should fix
- CPU bf16 in a test.
tests/app/invocations/test_vae_compute_device.py:46runs the CogView4 case in bf16 on CPU.tests/AGENTS.mdrules out CPU bf16 matmul because it can abort the worker on part of the Windows fleet. These are convolutions and windows-cpu passed, but low precision isn't what's under test here. Please run it in fp32 and patch the estimator with the existingfixed_working_memoryfixture. compute_deviceisn't told apart from weight residency. Every test hascompute_device=cpuwith CPU weights, so replacing the fix withnext(vae.parameters()).devicepasses on sd3, ernie, anima, kontext and flux2. That is the exact wrong approach the issue warns about for partial loading. One case withcompute_devicedifferent from the weights would close it.
Follow-up, not caused by this PR. A cpu_only FLUX VAE still crashes on two routes the issue didn't list: _prep_flux_fill_img_cond (flux_denoise.py:908-919) and the Control LoRA conditioning (:856-859, then flux/denoise.py:151). Both use the latents from vae_encode without moving them. Two .to(device, dtype) calls here, or a follow-up issue, would both work.
Nits
is_oom_errorinoom.py:35is shared by eleven call sites, while the description names only Kontext's retry.- The QA section cites Diffusers 0.41.0; the pin is 0.42.1.
- Dropping
device=vae_info.compute_devicefrom the sd3, cogview4 and qwen estimators passes every test.
|
Addressed the review in 857fb06.
The QA now records isolated Diffusers 0.42.1, CPU/meta limits, the Fill dtype-conversion change, and the shared OOM classifier's scope across eleven consumers. No physical accelerator or full-model result is claimed. |
Summary
VAE encoding inputs, memory estimates and tile decisions follow the loaded model's
compute_device. Encoded conditioning is then transferred to the device and dtype of its consuming transformer.The FLUX Fill and Control LoRA paths also handle a CPU VAE in an accelerator session. Fill keeps its pixels and boolean mask together before encoding, aligns the packed mask with the returned latents, and transfers the assembled conditioning to the session. Control LoRA transfers its VAE result before denoise concatenation.
Related Issues / Discussions
Closes #10014. Also covers the two additional FLUX routes identified in the review.
QA Instructions
The finalized follow-up fixtures fail on unchanged
23cd5f1in four cases: Fill and Control LoRA, each under CPU/meta session conditions. The two CPU cases expose a dtype mismatch; the meta cases expose an early pixel transfer or a cross-device concatenation.On this revision, 11 focused cases and 113 related cases pass across disjoint files (124 unique passes). The new four-case FLUX file also passes independently; those four are included in the 11. A real tiny fp32 VAE encodes with its unused decoder offloaded to meta, so using the first parameter's device fails inside the native encoder. Separate deliberate regression controls fail when that incorrect device lookup or any of the three estimator device arguments is substituted.
Validation used Windows, Python 3.12.14, Torch 2.13.0+cpu and the project's pinned Diffusers 0.42.1 installed in an isolated import target. Native pytest ran with
-n 0, bounded BLAS threads and isolated test roots. This is not the complete uv-locked environment. Ruff 0.11.2 lint/format checks,git diff --checkand normal commit hooks pass.VAE forwards use CPU fp32. Meta sessions and the transformer input boundary exercise routing without accelerator kernels. No physical GPU, full-model generation, real partial-cache loading, family E2E, RSS or speed result is claimed.
Review
The device contract uses
LoadedModel.compute_device, independently of current weight residency. Estimator spies verify both the device and reservation forwarding through the existingfixed_working_memoryfixture.Fill defers dtype conversion to the VAE owner. For fp32/fp16 VAEs this removes the former premature bf16 quantization, so those inputs are not claimed numerically identical to the old path. Boolean mask semantics remain unchanged.
The shared
is_oom_errorclassifier recognizes the two known PyTorch CPU allocator message formats. That classification applies to its eleven existing consumers, including Kontext's tile retry; no unrelated handler or retry policy is changed.Implementation and validation were assisted by OpenAI Codex.
Checklist
What's Newcopy (if doing a release after this PR)Open in [code]smith · Need help on this PR? Tag
@codesmith-botwith what you need.