mirror of
https://github.com/Comfy-Org/comfy-kitchen.git
synced 2026-11-04 23:37:42 +00:00
[GH-ISSUE #188] [gfx1201] hip backend missing bare (non-_dtype) dequant functions — silently falls back to slow single-threaded eager backend during model load #56
Labels
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Comfy-Org/comfy-kitchen#56
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @CS6 on GitHub (Sep 20, 2026).
Original GitHub issue: https://github.com/Comfy-Org/comfy-kitchen/issues/188
Summary
On an AMD Radeon AI PRO R9700 (RDNA4,
gfx1201), loading any quantized model whose weights go throughcomfy/ops.py's_load_quantized_module()path takes 10–60+ minutes for models in the tens-of-GB range, pegging a single CPU core at ~95-100% the whole time while GPU utilization stays near 0%.Root cause:
comfy_kitchen'shipbackend implements the_dtype-suffixed variant of several dequantization functions, but not the bare (no-suffix) variant thatcomfy/ops.pyactually calls during weight loading. SinceBackendRegistry's priority order is["hip", "cuda", "triton", "eager"]andhipdoesn't advertise the bare function name as a capability, dispatch silently falls through all the way toeager— a pure-Python/generic-PyTorch implementation with no ROCm acceleration — for every single weight tensor.This reproduces on a completely clean installation (official
rocm/pytorch:rocm10.0_ubuntu26.04_py3.14_pytorch_release_2.13.0Docker image,comfy-kitchen==0.2.35,amd-torch-device-gfx1201==2.13.0+rocm10.0.0installed alongside torch as required), so it is not an environment misconfiguration.Environment
gfx1201)rocm/pytorch:rocm10.0_ubuntu26.04_py3.14_pytorch_release_2.13.0(official AMD image)2.13.0+rocm10.0.0(+amd-torch-device-gfx1201==2.13.0+rocm10.0.0installed alongside, required separately for any kernel to dispatch at all — see note below)0.2.35(also reproduced on0.2.10)masteras of 2026-09-20ComfyUI_MinimaxH3HybridLoader/ComfyUI-MiniMax-H3-Turbo(MiniMax H3 video model,int8_convrot-quantized ~25GB text encoder + ~20GB diffusion transformer), but the same "Found quantization metadata version 1" / "Using MixedPrecisionOps for text encoder" hang has also been independently reported by other users loading unrelated models (e.g. Pixal3D/Trellis2) on the samegfx1201architecture — see "Related reports" below. So this does not appear to be model-specific.Steps to reproduce
gfx1201machine, install a cleancomfy-kitchen==0.2.35+ matching ROCm-10.0 torch stack (torch,amd-torch-device-gfx1201,rocm-sdk-core/rocm-sdk-libraries/rocm-sdk-device-gfx1201, all==...+rocm10.0.0/10.0.0).torch.ones(4,4,device='cuda')+1, fp16 matmul) — they do, confirming the base install is sound.comfy.ops.MixedPrecisionOpswithint8_convrot(or plainint8) quantization and a non-trivial weight count (hundreds to low thousands of tensors).ps -o pid,etimes,time,pcpuon the ComfyUI process shows a single thread pinned at ~90-100% CPU for the entire duration;rocm-smi --showuseshows ~0-3% GPU utilization the whole time.Root cause
comfy_kitchen/backends/hip/__init__.pydefinesdequantize_int8_convrot_weight_dtype(...)anddequantize_int8_simple_dtype(...), but never registers the baredequantize_int8_convrot_weight/dequantize_int8_simplenames thatcomfy/ops.py's model-loading path (_load_quantized_module→ weight dequant/requant) actually calls.comfy_kitchen's owncudabackend does implement both bare functions as one-line wrappers around the_dtypeversion with afloat32default:The
hipbackend has no equivalent — the bare name is simply absent from its_build_constraints()capability dict — so dispatch has nohipcandidate for that function name and falls through the priority list toeager.Confirmed fix (partial)
Adding the same one-line wrapper pattern to
comfy_kitchen/backends/hip/__init__.pyfor both functions, and adding the corresponding entries to_build_constraints(), does work — verified directly:(plus matching
"dequantize_int8_simple"/"dequantize_int8_convrot_weight"entries in_build_constraints(), copied from the_dtypeentries minus theoutput_dtype_codeparam.)However, this only partially fixes the hang. After applying it, the exact same model still hangs at the exact same log line for 30+ minutes.
dequantize_int8_embeddinghas nohipimplementation at all (not even a_dtypevariant to wrap) — this is almost certainly the actual remaining bottleneck for text-encoder loading specifically, since text encoders have large embedding tables and this function has no accelerated path whatsoever onhip. That one needs an actual native implementation, not a wrapper — beyond what I can contribute myself.Note: a second, unrelated blocker on the way to reproducing this
For anyone trying to reproduce: on a from-scratch ROCm 10.0 install,
torch.cuda.is_available()returnsTrueand the device name resolves correctly, but every kernel launch (includingtorch.ones(4,4,device='cuda')+1) fails withhipErrorInvalidImageunlessamd-torch-device-gfx1201==2.13.0+rocm10.0.0is also installed alongsidetorch/rocm-sdk-device-gfx1201(it's a separate package carrying torch's external "kernel pack" for the exact arch — not obviously implied by the official install docs). Not acomfy-kitchenbug, just a prerequisite worth knowing before debugging anything else on this chip.Related reports (independent confirmation this is a
gfx1201-wide pattern, not model-specific).to(device)overhead (~0.5s/tensor fixed cost) rather than this dispatch gap — likely a second, independent slow-path on this architecture, not the same bug, since--disable-mmapdid not resolve the hang reported here.comfy-kitchen'shipbackend: works fine in 93.99s on RDNA3 (7900XT,gfx1100), but hangs for 3+ minutes on RDNA4 (RX 9070,gfx1201) in the same_naf_hrcode path, with per-step timings showing the RDNA4-specific slowdown isolated to specific tensor-shape calls. Same generational pattern: RDNA3 fine, RDNA4 (gfx1201) broken.gfx1201/gfx1151kernel-dispatch regressions in the ROCm 10.0/torch 2.13 "kernel pack" architecture,7.14.0reported as the last known-good build across multiple of these.Ask
dequantize_int8_convrot_weight/dequantize_int8_simplewrappers to thehipbackend (patch above, happy to open a PR if useful).hipimplementation ofdequantize_int8_embeddingwould likely be needed to fully resolve model-loading hangs for models with quantized embedding tables (e.g. text encoders) ongfx1201.eagerfor a "should be accelerated" backend), rather than silent? This would have saved a lot of debugging time — the log gives no indication that a 25GB model is about to be processed through a generic Python fallback path.Note
I see #183 (open, not yet merged) is already tuning the HIP INT8 ConvRot compute kernel specifically for gfx1200/gfx1201 with H3-shaped projections (
@qweqweewqe7-create) — that's a different layer of the same code path (kernel geometry/perf, once dispatch actually reacheship) rather than this dispatch-gap issue, but tagging for visibility since it's clearly the same problem area and hardware. Would be great to get these two efforts pointed at each other.@0xDELUXA commented on GitHub (Sep 22, 2026):
Thanks for the detailed write-up.
The capability gap does not appear to be the cause of the hang. On gfx1200 (RX 9060 XT) with
comfy-kitchen 0.2.35, the eager/HIP difference reproduces exactly. However, none of those bare names are on the model-load path.comfy/ops.py's_load_quantized_moduledoes not call intocomfy-kitchenat all: it wraps the int8 weight andweight_scalein aQuantizedTensorand moves them to the device. With a hook onregistry.get_capable_backend, loading 200 int8 ConvRot 3072x3072 layers throughcomfy.ops.mixed_precision_ops()took 434 ms and made zerocomfy-kitchendispatches.At runtime, the int8 path already lands on HIP. The forward dispatches
int8_linear -> hip, andTensorWiseINT8Layout.dequantizecallsdequantize_int8_convrot_weight_dtype/dequantize_int8_simple_dtype, which also resolve to HIP. The baredequantize_int8_simple/dequantize_int8_convrot_weightare only reached if called directly, so wrapping them on HIP is harmless parity but will not change load time.The eager backend is also not a CPU fallback. It runs regular torch ops on the GPU tensors. A 5120x5120 ConvRot dequantize takes 3.8 ms on eager vs 0.96 ms on HIP, so even a model with around a thousand weights all going through eager would add seconds, not tens of minutes.
dequantize_int8_embeddinghas no CUDA implementation either; it is eager-only on every backend, and HIP mirrors CUDA's envelope here. It gathers only the requested rows on the GPU: 0.48 ms for 512 tokens from a 200k x 5120 int8 ConvRot table.On making fallbacks visible: backend selection is already logged at debug level on the
comfy_kitchen.dispatchlogger, sologging.getLogger("comfy_kitchen.dispatch").setLevel(logging.DEBUG)shows every choice.A single core pinned at 100% with the GPU idle right after "prepared for dynamic VRAM loading" points to host-side work rather than a kernel choice: safetensors mmap page-in, dynamic VRAM staging, or code-object loading from the ROCm 10 kernel pack (the TheRock issues you linked). The quickest way to pin it down is
py-spy dump --pid <comfyui pid>a few times during the hang; the Python stack will show exactly where the thread is. Running once with--disable-dynamic-vramand once with--disable-mmapwould also help separate those paths.