Skip to content

cuda: fp4pair, fp8pair and e4m3f in common/fp_pairs.cuh, SASS unchanged - #1555

Merged
ashhart merged 3 commits into
ashhart:mainfrom
jschmied:prims-1409-step3
Oct 29, 2026
Merged

ashhart merged 3 commits into
ashhart:mainfrom
jschmied:prims-1409-step3

Conversation

@jschmied

@jschmied jschmied commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

What

Step 3 of #1409. It is independent of #1550 (no shared files) and is a pure refactor: cuobjdump -sass is identical for every function of every image that includes a touched file.

The text-identical copies of three small decoders move into tf_common in a new header, common/fp_pairs.cuh:

  • fp4pair (two E2M1 codes to a bf16x2 pair): common/qmm_frag.cuh, prompt16.cu, nvfp4_experts.cu, nvfp4_experts_tile.cu;
  • fp8pair (two adjacent E4M3 bytes to a bf16x2 pair): drama3_fp8.cu, fp8_experts.cu;
  • e4m3f (one E4M3 scale to float, uint32_t argument): nvfp4_experts.cu, nvfp4_experts_tile.cu.

Each file takes them through a using declaration, so no call site changes, and qmm_frag::fp4pair still resolves the same way.

tools/zig/cuda_sass_identity.py's fp4pair-constant control now plants in common/fp_pairs.cuh, since that is where the constant lives now. Without that change the control would find no pattern and the tool would exit 1.

The gradient-serving pins of prompt16.cu and common/qmm_frag.cuh take the new bytes. Both matched on main. The pins of fp8_experts.cu and nvfp4_experts.cu already differ on main and are left as they are, as #1550 does for flashnext_batch.cu.

9 files, +48 / −50.

Left alone on purpose

These are not text-identical:

  • qmmf.cu's fp8pair spreads the bytes first;
  • qmmf.cu's e4m3f takes a uint8_t;
  • prompt16.cu's fp8pair takes a unit argument.

They would need their own SASS or float64 check.

Verification

  • SASS: base main dd0a9cc5e, head 8f1ccf336, nvcc 13.0, sm_80/86/89/120/121. 29 images, 1,695 functions: 0 changed, 0 added, 0 removed. The images are affine8, affine_prefill, block_attention, ck_experts, ck_lane, contract_controls, drama3_fp8, flashnext_attn, flashnext_fact, flashnext_hc, flashnext_hcf, fp8_experts, lane_gemv, nvfp4_experts, nvfp4_experts_tile, prefill_attention, prompt16, qmm, qmm_group, qmm_prefill, qmmf, qwen35, qwen35_kv8, route_rows, tree_attention, w4a8_prefill, window_attention, window_pages and window_rows.
    python3 tools/zig/cuda_sass_identity.py --repo . -j 3 --receipt sass.tsv origin/main HEAD
    
  • Planted controls: both go red, and the tool exits 0.
    • a changed fp4pair constant: 167 functions in 4 of 29 images;
    • a reversed warp_sum butterfly: 135 functions in 5 of 7 images.
  • zig build test-gradient-serving: the same set of differing pins as main. That test already fails on main, on contract_controls.cu among others.
  • lean: 425 problems, 425 on the base, 0 new.
  • zig build test -Dnvcc=/usr/local/cuda/bin/nvcc: passes (RC 0).

Part of #1409.

…rp_sum, SASS unchanged

The three remaining float warp_sum copies (xor butterfly 16..1) give way to common/reduce.cuh through a using
declaration, as in ashhart#1440. qwen4_gdn.cu is the checked-in text Gdn.cuda generates from flashnext_gdn.cu
(source_test), so both change together. qwen4_gdn_cuda_host.zig, which builds that text for the CPU, now strips
the include and the using declaration instead of the deleted function. flashnext_gdn.cu's gradient-serving pin
takes the new bytes; flashnext_batch.cu's two pins already differ on main and are left as they are.

cuobjdump -sass is identical for every function of the three images (65 functions, sm_80/86/89/120/121) with
nvcc 13.0 and 13.2, base prims-1409.
Step 3 of ashhart#1409. The text-identical copies move to tf_common in one header:
- fp4pair (E2M1 pair to bf16x2): qmm_frag.cuh, prompt16, nvfp4_experts and nvfp4_experts_tile;
- fp8pair (two adjacent E4M3 bytes to bf16x2): drama3_fp8 and fp8_experts;
- e4m3f (E4M3 scale to float): nvfp4_experts and nvfp4_experts_tile.

Each file takes them by a using-declaration, so no call site changes. qmm_frag keeps qmm_frag::fp4pair the same way.
Left out because their text differs: qmmf's fp8pair (bytes spread first) and e4m3f(uint8_t), and prompt16's
fp8pair with a unit argument.

cuda_sass_identity.py's fp4pair-constant control now plants in common/fp_pairs.cuh, where the constant lives.
…ytes fp_pairs.cuh leaves

Both pins matched main before this branch. fp8_experts.cu's and nvfp4_experts.cu's pins already differ on main and are left as they are, as ashhart#1550 does for flashnext_batch.cu.
ashhart added a commit to jschmied/TensorFold that referenced this pull request Oct 29, 2026
@ashhart
ashhart merged commit ab30560 into ashhart:main Oct 29, 2026
9 checks passed
ashhart added a commit that referenced this pull request Oct 29, 2026
@ashhart

ashhart commented Oct 29, 2026

Copy link
Copy Markdown
Owner

Thanks @jschmied, landed with #1550, #1555 and #1556 together on main (changelog in 5b6c254). We rebuilt every CUDA image from main and from the stack at sm_121 and sm_80: all 1,866 functions in the 104 images compile to identical SASS.

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.

2 participants