fix(quant): round scaled int8 casts to nearest - #4637
Open
skyguan92 wants to merge 1 commit into
Open
Conversation
The shared scaled INT8 conversion helpers used static_cast, which truncates toward zero and disagrees with torch quantization and the existing OPUS RMSNorm INT8 path. Round with __builtin_rintf before the integer cast and add a deterministic fused RMSNorm group-quant regression. Signed-off-by: guanjiawei <128683929+skyguan92@users.noreply.github.com>
Contributor
🏷️ CI GuideRuns automatically on every PR:
Extended tests (opt-in via labels):
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
__builtin_rintfbefore the integer conversion instead of truncating toward zero;rmsnorm_quantgroup-64 regression whose RMSNorm factor cancels from the expected value/max ratios.This aligns the shared HIP helper with
torch.roundquantization and with AITER's existing OPUS RMSNorm INT8 path, which already uses__builtin_rintf.Regression
On native gfx1100, the unmodified current-main helper matched truncation on every distinguishing fixture value:
b3c13c9The added test was compiled and run from scratch against current AITER main
b3c13c932207bef03aa3a8123bf34acad02f40d3:test_i8_group_quant_rounds_to_nearest;M=1, N=1024: per-token RMSNorm, add+RMSNorm per-token, and add+RMSNorm group-128.The fork commit is based on the fork's older upstream ancestor because the available OAuth credential cannot update workflow files. Cherry-picking PR head
35b4d832ac709302719f39589ea8e1bc3efaf19bonto current main produces replayb9f2417ac6d216066825711a48dad777ce5148ae, whose full tree SHA6428cf8cc322334947af46fa6237d50a5972f5efis identical to the directly tested current-main commitbdbd025919b3febe36c76b8b572ff7c9285f9f11.W7900D / DeepSeek V4 evidence
Environment: native
gfx1100with noHSA_OVERRIDE_GFX_VERSION, PyTorch2.9.1+gitff65f5b, HIP7.2.53211-e1a6bc5663. PyTorch reports 48 processor units for the selected device.The layer-local screen used official ModelScope
deepseek-ai/DeepSeek-V4-Flash-0731layer-0 weights, calibrated group-64 INT8 weights,M={1,8,16}, 3 hot samples x 20 repetitions, 20 synchronized 512-MiB shader-read cold samples, and the same W8A8 GEMM on both sides.(N,K)wqkv_a(1536,4096)wq_b(4096,1024)(512,4096)All 9 rows meet cosine >= 0.9995 and relative L2 <= 0.01 and are byte-exact across repeats. With the same
wq_bseed, the fused boundary improved from relative L20.0129448before the fix to0.00992086after it.This is not a claim that INT8 beats BF16 at every small projection:
wq_bM1/M8 hot results are 0.968x/0.977x versus BF16, and the shared gate/up cold geomean is 0.833x versus BF16. The contribution fixes the bottom-level INT8 contract and makes the existing fusion usable; schedule and model integration work remain separate.The DeepSeek-shaped performance run used an
e261b8f-based AITER source tree. The involved RMSNorm wrapper, HIP kernel, OPUS reference, and pre-patch shared helper blobs are byte-identical to current mainb3c13c9; the regression and focused upstream tests above were run directly fromb3c13c9.gfx1100 ISA / resources
For the exact BF16-to-INT8, block-128, no-residual fused kernel selected by the
N=1024test:0xde4 -> 0xe0cbytes (+40 bytes);v_rndne_f32instructions before the integer conversions;Checks
26.3.0check: pass0.15.7check: pass18.1.8check on the changed C++ hunk: passgit diff --check: passScope is the shared INT8 conversion contract and its fused RMSNorm regression. It does not change dispatch policy, quantization scale layout, or serving integration.