feat: support packed INT4 convrot models (#2276)

Co-authored-by: noctrex <noctrex@gmail.com>
This commit is contained in:
leejetandnoctrex authored and GitHub committed 2026-11-06 00:35:58 +08:00
1 parent 58bb3c1b1c
commit 7952693004
48 files changed
+2003 -102

No files matched your search

+40 -1
View File
@@ -100,7 +100,46 @@ The packed runtime activation tensor contains the I8 activation rows and their f
LoRA adapters are applied at runtime without modifying the INT8 weights. The INT8 convrot path computes the base linear output, while LoRA, LoHa, LoKr, and raw weight-difference adapters compute their output corrections from the original, unrotated activation and add them to the base output. `--lora-apply-mode auto` selects this path for models containing INT8 tensorwise weights. If `immediately` is requested, sd.cpp falls back to runtime application because merging an adapter would require dequantizing and rotating its weight update, then recalculating the per-row scales and requantizing the result.
The shared CUDA/HIP/MUSA convrot activation paths currently require a group size of `256`; other supported group sizes use CPU execution.
The shared CUDA/HIP/MUSA convrot activation paths support H64 and H256. Vulkan also supports H64 activation quantization; its INT8 matrix multiplication path currently requires H256.
## Packed INT4 convrot
ComfyUI `convrot_w4a4` and `asym_w4a8_int8` safetensors load directly, including
checkpoints that mix packed INT4, INT8 tensorwise, and floating-point layers.
Packed weights retain their checkpoint byte layout; they are not expanded or
converted to GGUF Q4 blocks at load time.
- `convrot_w4a4`: signed 4-bit weights, low nibble first, with F32 per-output
`weight_scale`. Activations use the same INT8 convrot quantization as above;
the format name does not select a native INT4 activation kernel.
- `asym_w4a8_int8`: 4-bit indices into `weight_codebook` (16 F32 values), F32
`weight_s_channel`, and F8_E4M3 `weight_s_rel` per 16 input features. The
metadata must specify `group_size: 16`. CPU evaluates the floating-point
codebook; GPU kernels requantize it to INT8 with `amax / 127`, introducing a
small additional rounding error.
Both formats imply convrot rotation even without a `convrot` flag; missing
`convrot_groupsize` defaults to 256.
Both formats reuse the convrot activation cache when the input scale is `1` and
produce F32 outputs with optional bias. CPU provides a portable implementation.
CUDA/HIP/MUSA use shared packed-weight kernels without requiring INT8 BLAS;
CUDA and supported AMD targets use packed byte-dot instructions, with portable
byte arithmetic for other targets. Vulkan requires integer dot product support
and at least 13312 bytes of shared memory for W4A4 or 16452 bytes for W4A8.
GPU W4 kernels require the logical input width to be divisible by 64; H64 and
H256 are supported. Other shapes use CPU fallback. HIP W4A8 selects wave64 WMMA
by the active compilation target's
intrinsic support, preferring the GFX12 fragment layout over the GFX11 layout.
There is no GPU architecture allowlist: newer targets supporting either
intrinsic automatically use its matching layout. Selection happens per device
image, including multi-architecture builds; targets supporting neither intrinsic
retain the integer-dot fallback. W4A4 retains integer dot products on HIP.
LoRA application remains at runtime, using the original unrotated activations
and logical weight dimensions. Packed weights and their codebook/scale tensors
are excluded from weight type conversion. `SD_USE_UPSTREAM_GGML` builds reject
these formats because they require the application extension API.
## Example