Conversation
…n.cpp)" This reverts commit 1014d0f.
|
Something off-topic: I've also successfully built SYCL build on Windows, and added standalone CUDA build on Linux. If the community is interested in this I would also open a PR for this |
|
Perhaps we can identify the specific operator involved and force it to use F32 precision. That could fix the issue while keeping the performance impact and VRAM increase minimal. |
|
I think providing an option for full F32 computation is reasonable. Since most weights of vae is F32, force quantizing to F16 is not quite a good idea. When the user uses VAE weights in BF16, we can just keep it and result almost no VRAM increase |
|
Thanks for working on this. I think Convolution support still varies considerably across ggml backends. The im2col + GEMM path can require a large temporary buffer, while some direct convolution paths lack an optimized implicit-GEMM implementation and can be much slower. BF16 support is also incomplete, so changing the default compute type requires checking the entire operation path, including fallbacks. I found several concrete issues in the current implementation:
For the specific Qwen Image 2.1 VAE issue, I think convolution scaling is a better fit. I checked the BF16 VAE file: its weights range from -4.90625 to 9.5, so converting the weights to FP16 does not cause overflow from excessive magnitude. The scaling change targets intermediate activation overflow. I've added a fixed I'd prefer to use that focused fix for this issue and revisit |
|
That's true. I just tested on CUDA using F32 and BF16, which can't cover all circumstances. |
Summary
This PR fixes Qwen Image 2.1 resulting images with white squares when writing alpha channels. The cause of this is that VAE weights are forced to be loaded and computed using FP16, while the Qwen Image 2.1 VAE decoder residual stream legitimately reaches magnitudes beyond the f16 range (±65504) in some regions. Then it becomes
+inf, which producesNaNin later computation, and be clamped to 255 when converting to uint8.This changes vae weights loading behavior to keeping original dtype in memory instead of converting to F16 (it also makes vae weights could be affected by
--tensor-type-rules, which couldn't before since F16 is hardcoded). The computation would use the same dtype as loaded weights unless a new parameter--vae-dtypeis specified (quantized dtypes likeq8_0would be F16). Besides,im2coluses F16 as long as input is not BF16 (which uses F32), so I also added a path to force using F32 when input is F32 for users using vae weights without quantization.Related Issue / Discussion
This is a solution for the issue left in #2021
fix #2024
Additional Information
It seems that Apple Metal does not support F32 conv, so it would fallback to CPU if F32 computation is used (as long as F32 or BF16 weights are used)
Another concern about Qwen Image 2.1: diffusers prefers LANCZOS input resizing (https://github.com/huggingface/diffusers/blob/e0118ade2f60234c41bacf40330a7e2f61108849/src/diffusers/image_processor.py#L92-L93), while Nearest is forced now; this model also has a default cfg 1.0 according to the diffusers repo (https://github.com/huggingface/diffusers/blob/e0118ade2f60234c41bacf40330a7e2f61108849/src/diffusers/pipelines/qwenimage21/pipeline_qwenimage21.py#L542-L544), while sd.cpp defaults to 7.0 globally.
I suggests that add model-specified default values for cfg scale. I'm still investigating the image resizing path
Checklist