Repository navigation
Check quantized embedding qparam dtypes against how the kernels read them - #23912
Shakhtar-Sankur wants to merge 2 commits into
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/23912
Note: Links to docs will display an error until the docs builds have been completed.
|
|
@pytorchbot label "release notes: ops & kernels" |
|
@Shakhtar-Sankur could you rebase and ping for review? Thanks |
f79810b to
460b8b9
Compare
|
@nil-is-all rebased onto main (it now sits on top of #23677), thanks. @JakeStevens @metascroy could you take a look when you have a moment? |
|
The fake implementations for the non-dtype |
…them The reference ops (exir/passes/_quant_patterns_and_replacements.py) require weight_zero_points to have the same dtype as weight_scales, and the variants without a dtype argument return the scales' dtype. The kernels instead read the zero points as the scales' type but checked them against the output dtype, and the .out variants read the scales as the output type without checking it. As a result, embedding_byte/2bit/4bit.dtype_out aborted on fp16 scales and zero points with a fp32 output, which the reference accepts, and accepted fp32 zero points with fp16 scales, reading them as fp16. The .out variants with fp16 scales and a fp32 output read past the end of the scales. Check the zero points against the scales, and in the .out variants check the scales against the output. The new tests for the 8-bit and 4-bit ops (2-bit shares the 4-bit code) fail without the change.
The fake kernels of embedding_2bit and embedding_4bit (the variants without a dtype argument) returned torch.nn.Embedding(...)(indices), which is always fp32. The reference ops return weight_scales.dtype, so with fp16 or bf16 scales export recorded fp32 for a tensor that is fp16 or bf16 at run time. Return weight_scales.dtype from both fakes. The new test compares each fake with its reference op for fp16, bf16 and fp32 scales; the fp16 and bf16 cases fail without the change.
460b8b9 to
e297841
Compare
|
Thanks @JakeStevens, good catch. The fake kernels for embedding_2bit and embedding_4bit now return weight_scales.dtype, matching the reference ops, and test_embedding_xbit_fake_dtype checks each fake against its reference op for fp16, bf16 and fp32 scales (the fp16 and bf16 cases fail without the fix). @nil-is-all I've rebased on main. Ready for review, thanks! |
Summary
The reference ops in exir/passes/_quant_patterns_and_replacements.py require weight_zero_points to share weight_scales' dtype, and the variants without a dtype argument return the scales' dtype. The kernels checked the zero points against the output dtype instead (while reading them as the scales' type), and the .out variants read the scales as the output type without checking it. So:
This checks the zero points against the scales, and the scales against the output in the .out variants.
Related to #23677 (index bounds check in the same kernels); the two changes are independent and merge cleanly in either order.
Test plan
Built quantized_kernels_test with CMake (Debug, -fsanitize=address).
Authored with AI assistance. I reviewed the change and ran the tests myself.
cc @larryliu0820 @manuelcandales @JakeStevens @nil-is-all