Skip to content

feat: add torch dequantization for IQ1_S, IQ1_M, IQ2_XXS, IQ2_S, IQ3_XXS, IQ3_S - #433

Open
octo-patch wants to merge 1 commit into
city96:mainfrom
octo-patch:feat/iq-lower-quant-dequant
Open

feat: add torch dequantization for IQ1_S, IQ1_M, IQ2_XXS, IQ2_S, IQ3_XXS, IQ3_S#433
octo-patch wants to merge 1 commit into
city96:mainfrom
octo-patch:feat/iq-lower-quant-dequant

Conversation

@octo-patch

Copy link
Copy Markdown

Closes #405

Problem

Lower IQ quant types (IQ1_S, IQ1_M, IQ2_XXS, IQ2_S, IQ3_XXS, IQ3_S) currently fall back to the slow numpy path in dequantize_tensor:

# this is incredibly slow
tqdm.write(f"Falling back to numpy dequant for qtype: ...")
new = gguf.quants.dequantize(tensor.cpu().numpy(), qtype)

This makes loading models quantized with these formats (e.g. Unsloth UD quants used as text encoders) very slow.

Solution

Implements native PyTorch dequantization functions for all six missing IQ quant types, using the quantization grids already provided by the gguf Python package.

The implementations follow the same pattern as the existing IQ4_NL and IQ4_XS dequantizers and were cross-referenced against the numpy reference implementation in gguf.quants.

Testing

All new functions are verified against gguf.quants.dequantize() (the numpy reference):

Q8_0:    max_diff=0.000000 ✓
Q6_K:    max_diff=0.000000 ✓
IQ4_NL:  max_diff=0.000000 ✓
IQ4_XS:  max_diff=0.000000 ✓
IQ3_S:   max_diff=0.000000 ✓
IQ3_XXS: max_diff=0.000000 ✓
IQ2_S:   max_diff=0.000000 ✓
IQ2_XXS: max_diff=0.000000 ✓
IQ1_M:   max_diff=0.000000 ✓
IQ1_S:   max_diff=0.000000 ✓

…XXS, IQ3_S

Implements native PyTorch dequantization functions for lower IQ quant types,
replacing the slow numpy fallback path for models quantized with these formats
(e.g. Unsloth UD quants used as text encoders).

All six new functions are verified against gguf.quants.dequantize() reference.
@SSJGabraham

Copy link
Copy Markdown

Tested this and it works well for IQ3_S in my setup.

@octo-patch

Copy link
Copy Markdown
Author

Thanks for testing @SSJGabraham! Great to hear IQ3_S is working well. If you get a chance to try any of the other quant types (IQ1_S, IQ1_M, IQ2_XXS, IQ2_S, IQ3_XXS), would love to hear how those work for you too.

@SSJGabraham

Copy link
Copy Markdown

@octo-patch One thing I noticed is that when I first ran a test, I thought I was using a IQ3_S, but it was actually IQ3_M, which if I am not mistaken was not listed in your new methods or in your summary above, but it still worked without reverting to the slow numpy path. I didn't notice a slowdown and I did not get a stream of messages in my console about it. When I switched to the proper IQ3_S model I intended to use, performance was identical.

Was this expected?

ChrisColeTech added a commit to ChrisColeTech/ComfyUI-GGUF-Loader that referenced this pull request Aug 12, 2026
Cherry-pick production fixes from city96/ComfyUI-GGUF open PRs:
- city96#472 dequant device-constant cache (major LTX/sampling speedup)
- city96#433 IQ1/IQ2/IQ3 torch dequant (extra TE quants)
- city96#470 QK-norm .scale→.weight (silent NaN/black Flux-compat)
- city96#467 dequant bare nn.Parameters (LTX learnable_registers)
- city96#392 lumina2/zimage pad token shape fix
- city96#456/city96#468 GGMLTensor dtype + dequantize() for core cast path
- city96#461 WeightAdapter-aware move_patch_to_device
- city96#469 force_patch on partial load/unload
- city96#440/city96#436 mistral3 TE, city96#438 qwen35, qwen2 allowlist
- city96#473 partial: Qwen3-VL deepstack mmproj map for MiniMax H3 TE

Skipped mega/draft rewrites (city96#459, full city96#473 LazyGGUFReader, city96#336 Triton).
See PR_BACKPORT.md for the full matrix.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

More IQ quant types and fix for torch.compile

2 participants