mirror of
https://github.com/Comfy-Org/comfy-kitchen.git
synced 2026-11-04 23:37:42 +00:00
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#143
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?
📋 Pull Request Information
Original PR: https://github.com/Comfy-Org/comfy-kitchen/pull/97
Author: @0xDELUXA
Created: 8/6/2026
Status: ✅ Merged
Merged: 8/7/2026
Merged by: @comfyanonymous
Base:
main← Head:amd/hip-w4a8-int8📝 Commits (1)
e66f734HIP port of #90: grouped W4A8 over the INT8 GEMM📊 Changes
10 files changed (+839 additions, -24 deletions)
View changed files
📝
comfy_kitchen/backends/hip/CMakeLists.txt(+1 -0)📝
comfy_kitchen/backends/hip/__init__.py(+288 -0)📝
comfy_kitchen/backends/hip/dlpack_bindings.cpp(+84 -4)📝
comfy_kitchen/backends/hip/gemm_wmma.h(+5 -3)➕
comfy_kitchen/backends/hip/launchers.h(+36 -0)📝
comfy_kitchen/backends/hip/ops/convrot_w4a4.hip(+3 -3)📝
comfy_kitchen/backends/hip/ops/gemm_fp8.hip(+3 -3)📝
comfy_kitchen/backends/hip/ops/gemm_int8.hip(+16 -11)➕
comfy_kitchen/backends/hip/ops/w4a8_dequant.hip(+182 -0)📝
tests/test_hip_wmma.py(+221 -0)📄 Description
Ports the AsymW4A8Int8 path from #90 to the HIP backend, which registered none of it and so fell through to eager on ROCm. Rebased on #96; that follow-up needed no HIP work (see below).
What this adds
ops/w4a8_dequant.hip: grouped int4 -> int8 weight decode. One thread reads 8 packed bytes and writes 16 int8 through a uint4 store, fp32 and e4m3 group scales via one templated kernel, optional codebook staged in LDS. Reusesfp8_utils.hfor the e4m3 decode.dequantize_w4a8_int8_weightandw4a8_int8_linearplus constraints. The linear feeds the decoded weight into the existing WMMAint8_linearwithconvrot=True, so the activation rotation stays in the fused quantizer.w4a8_int8_linearis in_WMMA_ONLY_OPS, so RDNA2 routes it to triton/eager; the decode is elementwise and stays registered there.ldcrow stride so a chunk can write an N-column slice of the output; the fp8 and int4 GEMMs pass N and are unchanged. The weight is decoded a chunk at a time so it is still cached when the GEMM reads it back, instead of the whole[N, K]int8 weight round-tripping through global memory.quantize_w4a8_int8_weightis deliberately not registered. CUDA's version exists to use its native ConvRot rotate kernel, which HIP does not have, and that rotate measures at 0.1-0.2% of quantize time, so eager's packing math is what runs either way.Chunk sizing
The chunk width targets the device's own L2, capped at the CUDA backend's 4096 columns so a shallow K does not widen a chunk pointlessly and floored at 1024 so a deep K does not starve the GEMM's N grid. Chunking is limited to M <= 64, the conservative end of where it won on every shape tried: above that the weight is decoded in one pass, which is what this path did before chunking, so a part whose crossover sits higher loses the extra win rather than regressing. Both knobs are overridable via
COMFY_KITCHEN_W4A8_CHUNK_COLSandCOMFY_KITCHEN_W4A8_CHUNK_MAX_ROWS.Measurements (gfx1200, chunked vs single pass, min of 5x100 iters)
Against the eager fallback this replaces, the whole path is 4.6x to 23x faster.
On #96
The frozen codebook LUT, the row-chunked quantize and the
codebook_tensorkwarg all live in the shared eager layer, which the HIP backend inherits because it does not registerquantize_w4a8_int8_weight. #96 does change what the packer emits, so there is a test that the HIP decode is bit exact against eager on a row-chunked quantize and on a requantize with a pinned codebook.Testing
test_hip_wmma.pyandtest_hip_dispatch.py.Only ran on gfx1200. The 17-target fat binary builds clean, and the decode kernel compiles to identical ISA on gfx1030, gfx1100, gfx1151 and gfx1201 (31 VGPRs, no scratch spills, same vectorized load/store), but RDNA2/3/3.5 are compile and disassemble only here. The
ldcchange touchesgemm_wmma.h, shared by the fp8, int8 and int4 GEMMs on every family, so a check on a 7900 or 6800 would be welcome.Required
Core PR:
https://github.com/Comfy-Org/ComfyUI/pull/15308
Test model:
https://huggingface.co/Kijai/MiniMax-H3-experimental/blob/main/minimax_h3_fl2va_pruned_w4a8_mixed.safetensors
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.