Skip to content

feat(quant): implement fp4_act_quant Triton kernel for DeepSeek-V4 (#807)#1479

Open
haowu1234 wants to merge 1 commit into
ROCm:mainfrom
haowu1234:codex/fp4-act-quant-kernel
Open

feat(quant): implement fp4_act_quant Triton kernel for DeepSeek-V4 (#807)#1479
haowu1234 wants to merge 1 commit into
ROCm:mainfrom
haowu1234:codex/fp4-act-quant-kernel

Conversation

@haowu1234

Copy link
Copy Markdown

Summary

Implement the fp4_act_quant kernel (BF16 → packed FP4 e2m1 uint8 + E8M0 scale) as identified in the #807 kernel gap analysis. This replaces the torch fallback for the DeepSeek-V4 Indexer Q and Compressor KV quantization paths.

Changes

  • atom/model_ops/quant_v4.py (+395/-23): Add Triton JIT kernel _fp4_act_quant_kernel with column-wise load, per-row amax + ue8m0 scale, FP4 e2m1 snapping, 4-bit nibble encoding, and pairwise pack into uint8. New public API fp4_act_quant(x) → (packed_uint8, scale_e8m0). fp4_act_quant_inplace preserved as QAT round-trip shim.
  • tools/test_fp4_act_quant.py (new, +343): Standalone correctness test (Triton vs torch, roundtrip, pack format, edge cases) and benchmark via direct module load (no aiter dependency).

Pack format

Matches existing dequant_fp4_e2m1:

byte = (nibble_high << 4) | nibble_low
nibbles 0-7  → positive magnitudes {0, 0.5, 1, 1.5, 2, 3, 4, 6}
nibbles 8-15 → same magnitudes negative
scale = float8_e8m0fnu, per-1×32 block

Validation (MI300X VF, ROCm 7.1, Triton 3.6)

Correctness:

  • 13 shapes × block_sizes = all packed_diff=0, scale_diff=0
  • Roundtrip (quant → dequant_fp4_e2m1) off_grid=0.00
  • Edge cases: zeros, constants, extreme values, dtype preservation all pass

Performance vs torch fallback:

Shape Speedup
DSv4 Indexer kv (1,128,256) 44.9x
(16,128,256) 181.8x
(32,512) 22.6x

Closes: #807 (fp4_act_quant sub-task)

…OCm#807)

Add production BF16 → packed FP4 e2m1 quantize kernel for the
DeepSeek-V4 Indexer and Compressor paths on AMD MI300X.

Highlights:
- _fp4_act_quant_kernel: Triton JIT kernel with column-wise load,
  per-row amax + ue8m0 scale, FP4 e2m1 snapping to 8 magnitudes,
  4-bit nibble encode, and pairwise pack into uint8
- _fp4_act_quant_torch: pure-torch reference with identical output
- fp4_act_quant: main API returning (packed_uint8, scale_e8m0)
- fp4_act_quant_inplace: QAT round-trip shim preserved for compat
- tools/test_fp4_act_quant.py: standalone correctness + benchmark

Pack format (matching dequant_fp4_e2m1):
  byte = (nibble_high << 4) | nibble_low, 2 FP4 per byte
  nibbles 0-7 = positive magnitudes, 8-15 = same negative
  scale = float8_e8m0fnu, per-1×32 block

Validated on MI300X (gfx942, ROCm 7.1, Triton 3.6):
  - 13 shapes × 3 block_sizes all packed_diff=0, scale_diff=0
  - roundtrip (quant + dequant) off_grid=0.00
  - 44x speedup on DSv4 Indexer kv (1,128,256)
  - 182x peak on (16,128,256)

Refs: ROCm#807
@valarLip
valarLip requested a review from junhaha666 July 6, 2026 15:12
@junhaha666

Copy link
Copy Markdown
Contributor

Hello, we plan to use the kernel that combines Hadamard transformation and fp4 quantization in this PR ROCm/aiter#4029

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.

[Kernel Gap Analysis] DeepSeek-V4 AMD Porting — Block-by-Block Kernel Inventory

2 participants