Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
305 commits
Select commit Hold shift + click to select a range
f6ad7a2
Merge the H3 prior-art runner fix into PR #487
fusheng-ji Oct 8, 2026
b4c9fd5
Merge the H3 prior-art runner fix into PR #488
fusheng-ji Oct 8, 2026
6231a8c
Merge the H3 prior-art runner fix into PR #489
fusheng-ji Oct 8, 2026
4b01e4f
fix(scripts): name the failing check in the H3 prior-art figure
fusheng-ji Oct 8, 2026
6acdd42
Merge the H3 prior-art figure fix into PR #484
fusheng-ji Oct 8, 2026
0be03cc
Merge the H3 prior-art figure fix into PR #485
fusheng-ji Oct 8, 2026
c06b1e0
Merge the H3 prior-art figure fix into PR #486
fusheng-ji Oct 8, 2026
0460cc7
Merge the H3 prior-art figure fix into PR #487
fusheng-ji Oct 8, 2026
052f5cb
Merge the H3 prior-art figure fix into PR #488
fusheng-ji Oct 8, 2026
875e2a1
Merge the H3 prior-art figure fix into PR #489
fusheng-ji Oct 8, 2026
d10034c
fix(scripts): shorter batch-invariance panel title in the H3 prior-ar…
fusheng-ji Oct 8, 2026
d7dba15
Merge the H3 prior-art figure fix into PR #484
fusheng-ji Oct 8, 2026
7158413
Merge the H3 prior-art figure fix into PR #485
fusheng-ji Oct 8, 2026
213d6ef
Merge the H3 prior-art figure fix into PR #486
fusheng-ji Oct 8, 2026
3098f4a
Merge the H3 prior-art figure fix into PR #487
fusheng-ji Oct 8, 2026
5f4253d
Merge the H3 prior-art figure fix into PR #488
fusheng-ji Oct 8, 2026
49287fc
Merge the H3 prior-art figure fix into PR #489
fusheng-ji Oct 8, 2026
9bf0605
docs(h3): adaln_row_gather vs existing implementations (B200, 6c900ae)
fusheng-ji Oct 8, 2026
dd35c14
docs(h3): gate_residual vs existing implementations (B200, 4010854)
fusheng-ji Oct 8, 2026
3146af1
docs(h3): timestep_sinusoid vs existing implementations (B200, 7a82917)
fusheng-ji Oct 8, 2026
4c040db
docs(h3): timestep_mlp vs existing implementations (B200, ffd958a)
fusheng-ji Oct 8, 2026
28cba87
docs(h3): adaln_projection vs existing implementations (B200, c88691c)
fusheng-ji Oct 8, 2026
656b64b
docs(h3): norm_modulate vs existing implementations (B200, ee83dec)
fusheng-ji Oct 8, 2026
8805329
docs(h3): final_adaln_out vs existing implementations (B200, 03da729)
fusheng-ji Oct 8, 2026
f9c5a8c
Merge the H3 prior-art evidence into PR #484
fusheng-ji Oct 8, 2026
076104c
Merge the H3 prior-art evidence into PR #485
fusheng-ji Oct 8, 2026
3908e8f
Merge the H3 prior-art evidence into PR #486
fusheng-ji Oct 8, 2026
f9d7768
Merge the H3 prior-art evidence into PR #487
fusheng-ji Oct 8, 2026
2d1b9d0
Merge the H3 prior-art evidence into PR #488
fusheng-ji Oct 8, 2026
64fb1fa
Merge the H3 prior-art evidence into PR #489
fusheng-ji Oct 8, 2026
2e120f2
fix(scripts): readable H3 prior-art figure when errors are close or l…
fusheng-ji Oct 8, 2026
0ea4545
Merge the H3 prior-art figure layout fix into PR #484
fusheng-ji Oct 8, 2026
56bcee0
Merge the H3 prior-art figure layout fix into PR #485
fusheng-ji Oct 8, 2026
ef45a37
Merge the H3 prior-art figure layout fix into PR #486
fusheng-ji Oct 8, 2026
0329d03
Merge the H3 prior-art figure layout fix into PR #487
fusheng-ji Oct 8, 2026
1d1e739
Merge the H3 prior-art figure layout fix into PR #488
fusheng-ji Oct 8, 2026
8136ac3
Merge the H3 prior-art figure layout fix into PR #489
fusheng-ji Oct 8, 2026
919b67d
Merge test-h3 refactor and migrate H3 timestep validation
fusheng-ji Oct 10, 2026
ce16ef9
Merge test-h3 refactor and migrate H3 timestep MLP validation
fusheng-ji Oct 10, 2026
56e31ce
Merge test-h3 refactor and migrate H3 kernels, tools, and tests
fusheng-ji Oct 10, 2026
c3fad21
Merge test-h3 refactor and migrate H3 kernels, tools, and tests
fusheng-ji Oct 10, 2026
e004499
Merge test-h3 refactor and migrate H3 kernels, tools, and tests
fusheng-ji Oct 10, 2026
d22c1f8
Merge migrated H3 dependency PR #483
fusheng-ji Oct 10, 2026
4fe7296
Merge migrated H3 dependency PR #484
fusheng-ji Oct 10, 2026
96b0475
Merge test-h3 refactor and migrate H3 kernels, tools, and tests
fusheng-ji Oct 10, 2026
4f9da3d
Merge migrated H3 dependency PR #485
fusheng-ji Oct 10, 2026
d8039fd
Merge test-h3 refactor and migrate H3 kernels, tools, and tests
fusheng-ji Oct 10, 2026
a427494
Merge migrated H3 dependency PR #486
fusheng-ji Oct 10, 2026
fdc58d4
Merge migrated H3 dependency PR #487
fusheng-ji Oct 10, 2026
2737567
Merge migrated H3 dependency PR #488
fusheng-ji Oct 10, 2026
78b8942
docs(h3): point row-gather validation to migrated tests
fusheng-ji Oct 10, 2026
1481baa
Merge migrated validation documentation from PR #486
fusheng-ji Oct 10, 2026
6682e76
Merge migrated validation documentation from PR #487
fusheng-ji Oct 10, 2026
5ae2256
Merge migrated validation documentation from PR #488
fusheng-ji Oct 10, 2026
bf902e4
fix(h3): keep timestep_sinusoid_h3 out of fast-math builds
fusheng-ji Oct 13, 2026
0c5d8ed
Merge branch 'test-h3' into feat/h3-timestep-sinusoid
fusheng-ji Oct 13, 2026
b4b58b8
build(h3): gate every H3 bitwise kernel on one fast-math guard
fusheng-ji Oct 13, 2026
231de16
test(h3): skip the CUDA chain e2e when the H3 kernels are not built
fusheng-ji Oct 13, 2026
e04594b
Merge feat/h3-timestep-sinusoid into feat/h3-timestep-mlp-fp32
fusheng-ji Oct 13, 2026
fcac217
Merge feat/h3-timestep-mlp-fp32 into feat/h3-adaln-projection-3mod
fusheng-ji Oct 13, 2026
9243718
Merge feat/h3-adaln-projection-3mod into feat/h3-adaln-row-gather
fusheng-ji Oct 13, 2026
b52916a
test(h3): skip the CUDA chain backward e2e when the H3 kernels are no…
fusheng-ji Oct 13, 2026
db55298
Merge feat/h3-adaln-row-gather into feat/h3-rmsnorm
fusheng-ji Oct 13, 2026
f75ff23
Merge feat/h3-rmsnorm into feat/h3-adaln-gate-residual
fusheng-ji Oct 13, 2026
2a72708
Merge feat/h3-adaln-gate-residual into feat/h3-final-adaln-out
fusheng-ji Oct 13, 2026
be6a94a
tools(h3): direct bitwise comparison of reuse candidates
fusheng-ji Oct 13, 2026
367883a
evidence(h3): timestep_sinusoid direct bitwise comparison on B200
fusheng-ji Oct 13, 2026
73939f2
Merge feat/h3-timestep-sinusoid into feat/h3-timestep-mlp-fp32
fusheng-ji Oct 13, 2026
1a21cd6
evidence(h3): timestep_mlp direct bitwise comparison on B200
fusheng-ji Oct 13, 2026
50d1e92
Merge feat/h3-timestep-mlp-fp32 into feat/h3-adaln-projection-3mod
fusheng-ji Oct 13, 2026
c4f6145
evidence(h3): adaln_projection direct bitwise comparison on B200
fusheng-ji Oct 13, 2026
5fef115
Merge feat/h3-adaln-projection-3mod into feat/h3-adaln-row-gather
fusheng-ji Oct 13, 2026
62f8009
test(h3): fix the flaky FP32 table-gradient check in adaln_modulation
fusheng-ji Oct 13, 2026
7aeb6ba
evidence(h3): adaln_row_gather direct bitwise comparison on B200
fusheng-ji Oct 13, 2026
8379783
Merge feat/h3-adaln-row-gather into feat/h3-rmsnorm
fusheng-ji Oct 13, 2026
cad31b9
evidence(h3): norm_modulate direct bitwise comparison on B200
fusheng-ji Oct 13, 2026
a746bff
Merge feat/h3-rmsnorm into feat/h3-adaln-gate-residual
fusheng-ji Oct 13, 2026
3bbcca4
evidence(h3): gate_residual direct bitwise comparison on B200
fusheng-ji Oct 13, 2026
8cb4abe
Merge feat/h3-adaln-gate-residual into feat/h3-final-adaln-out
fusheng-ji Oct 13, 2026
2809990
evidence(h3): final_adaln_out direct bitwise comparison on B200
fusheng-ji Oct 13, 2026
49fa04a
test(h3): round the projection golden's activation from the FP32 SiLU
fusheng-ji Oct 13, 2026
5783276
Merge feat/h3-adaln-projection-3mod into feat/h3-adaln-row-gather
fusheng-ji Oct 13, 2026
ff3e3f3
Merge feat/h3-adaln-row-gather into feat/h3-rmsnorm
fusheng-ji Oct 13, 2026
3310212
Merge feat/h3-rmsnorm into feat/h3-adaln-gate-residual
fusheng-ji Oct 13, 2026
3b618cd
Merge feat/h3-adaln-gate-residual into feat/h3-final-adaln-out
fusheng-ji Oct 13, 2026
55370d6
test(h3): require exact dW/db equality in the projection golden check
fusheng-ji Oct 13, 2026
a07f1ed
Merge feat/h3-adaln-projection-3mod into feat/h3-adaln-row-gather
fusheng-ji Oct 13, 2026
2dc21b8
Merge feat/h3-adaln-row-gather into feat/h3-rmsnorm
fusheng-ji Oct 13, 2026
2c27639
Merge feat/h3-rmsnorm into feat/h3-adaln-gate-residual
fusheng-ji Oct 13, 2026
a43b952
Merge feat/h3-adaln-gate-residual into feat/h3-final-adaln-out
fusheng-ji Oct 13, 2026
0d433f6
test(h3): round the projection forward golden from the FP32 SiLU, req…
fusheng-ji Oct 13, 2026
60aa286
Merge feat/h3-adaln-projection-3mod into feat/h3-adaln-row-gather
fusheng-ji Oct 13, 2026
c8659cf
Merge feat/h3-adaln-row-gather into feat/h3-rmsnorm
fusheng-ji Oct 13, 2026
9c76b32
Merge feat/h3-rmsnorm into feat/h3-adaln-gate-residual
fusheng-ji Oct 13, 2026
76542aa
Merge feat/h3-adaln-gate-residual into feat/h3-final-adaln-out
fusheng-ji Oct 13, 2026
579775f
fix(h3): round the adaln_projection golden's activation from the FP32…
fusheng-ji Oct 13, 2026
61d23ad
Merge feat/h3-adaln-projection-3mod into feat/h3-adaln-row-gather
fusheng-ji Oct 13, 2026
0032d07
Merge feat/h3-adaln-row-gather into feat/h3-rmsnorm
fusheng-ji Oct 13, 2026
81741e9
Merge feat/h3-rmsnorm into feat/h3-adaln-gate-residual
fusheng-ji Oct 13, 2026
e7d1a7f
Merge feat/h3-adaln-gate-residual into feat/h3-final-adaln-out
fusheng-ji Oct 13, 2026
a4bc99f
fix(h3): round the final_adaln_out goldens' activation from the FP32 …
fusheng-ji Oct 13, 2026
068fcaa
evidence(h3): regenerate adaln_projection_3mod report after the golde…
fusheng-ji Oct 13, 2026
a00939e
Merge feat/h3-adaln-projection-3mod into feat/h3-adaln-row-gather
fusheng-ji Oct 13, 2026
ecb30e2
evidence(h3): regenerate adaln_row_gather report and chain replay aft…
fusheng-ji Oct 13, 2026
4315cee
Merge feat/h3-adaln-row-gather into feat/h3-rmsnorm
fusheng-ji Oct 13, 2026
a1e37ef
evidence(h3): regenerate the row-gather report on the newer runner af…
fusheng-ji Oct 13, 2026
d8a4a69
Merge feat/h3-rmsnorm into feat/h3-adaln-gate-residual
fusheng-ji Oct 13, 2026
a7605c6
Merge feat/h3-adaln-gate-residual into feat/h3-final-adaln-out
fusheng-ji Oct 13, 2026
7d716f2
evidence(h3): regenerate final_adaln_out report and chain replay afte…
fusheng-ji Oct 13, 2026
a6c8545
fix(h3): seed the row-gather op-backward check in the evidence report
fusheng-ji Oct 13, 2026
29b07c5
Merge feat/h3-adaln-row-gather into feat/h3-rmsnorm
fusheng-ji Oct 13, 2026
cbbfaed
evidence(h3): regenerate the row-gather report with the seeded op-bac…
fusheng-ji Oct 13, 2026
6136f31
Merge feat/h3-adaln-row-gather into feat/h3-rmsnorm
fusheng-ji Oct 13, 2026
fe0350c
evidence(h3): regenerate this branch's row-gather report with the see…
fusheng-ji Oct 13, 2026
9592623
Merge feat/h3-rmsnorm into feat/h3-adaln-gate-residual
fusheng-ji Oct 13, 2026
578f9db
Merge feat/h3-adaln-gate-residual into feat/h3-final-adaln-out
fusheng-ji Oct 13, 2026
8ea6bbe
Merge feat/h3-timestep-mlp-fp32 into feat/h3-adaln-projection-3mod
fusheng-ji Oct 13, 2026
fb1bd8a
fix(h3): seed the timestep_mlp timing inputs in the evidence report
fusheng-ji Oct 13, 2026
169af74
Merge feat/h3-adaln-projection-3mod into feat/h3-adaln-row-gather
fusheng-ji Oct 13, 2026
7f2fa85
fix(h3): seed the adaln_projection timing and invariance inputs in th…
fusheng-ji Oct 13, 2026
2553881
fix(h3): seed the row-gather timing inputs in the evidence report
fusheng-ji Oct 13, 2026
9778e66
Merge feat/h3-adaln-row-gather into feat/h3-rmsnorm
fusheng-ji Oct 13, 2026
95186cb
fix(h3): seed the plain-RMSNorm inputs of the norm evidence check
fusheng-ji Oct 13, 2026
8725b3d
test(h3): let the CPU timing shim accept seeded CUDA generators
fusheng-ji Oct 13, 2026
9b95c4a
Merge feat/h3-rmsnorm into feat/h3-adaln-gate-residual
fusheng-ji Oct 13, 2026
de6a224
Merge feat/h3-adaln-gate-residual into feat/h3-final-adaln-out
fusheng-ji Oct 13, 2026
9ba6ce6
docs: move the measurement outputs out of the pull request
fusheng-ji Oct 19, 2026
8132d06
docs: move the measurement outputs out of the pull request
fusheng-ji Oct 19, 2026
06bf572
docs: move the measurement outputs out of the pull request
fusheng-ji Oct 19, 2026
e26e369
docs: move the measurement outputs out of the pull request
fusheng-ji Oct 19, 2026
2985fd2
docs: move the measurement outputs out of the pull request
fusheng-ji Oct 19, 2026
a8e5901
docs: move the measurement outputs out of the pull request
fusheng-ji Oct 19, 2026
39fb03d
docs: move the measurement outputs out of the pull request
fusheng-ji Oct 19, 2026
674a0dc
Merge branch 'test-h3' into feat/h3-timestep-sinusoid
Flink-ddd Oct 21, 2026
e504029
docs: point commit hashes at the rewritten history
fusheng-ji Oct 23, 2026
3b74ce3
docs: point commit hashes at the rewritten history
fusheng-ji Oct 23, 2026
441e000
docs: point commit hashes at the rewritten history
fusheng-ji Oct 23, 2026
1a8e7b2
docs: point commit hashes at the rewritten history
fusheng-ji Oct 23, 2026
26a7cab
docs: point commit hashes at the rewritten history
fusheng-ji Oct 23, 2026
3801808
docs: point commit hashes at the rewritten history
fusheng-ji Oct 23, 2026
428baa1
docs: point commit hashes at the rewritten history
fusheng-ji Oct 23, 2026
5445e9b
Merge test-h3 into feat/h3-timestep-sinusoid
fusheng-ji Oct 25, 2026
897601c
Merge test-h3 into feat/h3-timestep-mlp-fp32
fusheng-ji Oct 25, 2026
6c62cf9
Merge test-h3 into feat/h3-adaln-projection-3mod
fusheng-ji Oct 25, 2026
372544c
Merge test-h3 into feat/h3-adaln-row-gather
fusheng-ji Oct 25, 2026
a548fb0
Merge test-h3 into feat/h3-rmsnorm
fusheng-ji Oct 25, 2026
1cacd95
Merge test-h3 into feat/h3-adaln-gate-residual
fusheng-ji Oct 25, 2026
8624852
Merge test-h3 into feat/h3-final-adaln-out
fusheng-ji Oct 25, 2026
cb9828f
fix(h3): time competing callables in a shuffled order and fix the sin…
fusheng-ji Oct 25, 2026
a74b1a5
fix(h3): record which weights the timestep MLP evidence used
fusheng-ji Oct 25, 2026
95df2a9
fix(h3): time competing callables in a shuffled order and fix the sin…
fusheng-ji Oct 25, 2026
9a748eb
fix(h3): time candidate and provider with the rotating harness of the…
fusheng-ji Oct 26, 2026
9beb140
fix(h3): keep the weight source on every timestep MLP perf row
fusheng-ji Oct 26, 2026
c19a6e5
fix(h3): time candidate and provider with the rotating harness of the…
fusheng-ji Oct 26, 2026
a5d1557
fix(h3): use one timing harness across the stacked PRs
fusheng-ji Oct 26, 2026
343fa40
fix(h3): use one timing harness across the stacked PRs
fusheng-ji Oct 26, 2026
c80704f
fix(h3): use one timing harness across the stacked PRs
fusheng-ji Oct 26, 2026
31f342d
fix(h3): use one timing harness and record the MLP weight source addi…
fusheng-ji Oct 26, 2026
62db9c6
Merge feat/h3-timestep-sinusoid into feat/h3-adaln-projection-3mod
fusheng-ji Oct 26, 2026
5160b8b
Merge feat/h3-adaln-projection-3mod into feat/h3-adaln-row-gather
fusheng-ji Oct 26, 2026
7ec2964
Merge feat/h3-adaln-row-gather into feat/h3-rmsnorm
fusheng-ji Oct 26, 2026
c08d9ee
Merge feat/h3-rmsnorm into feat/h3-adaln-gate-residual
fusheng-ji Oct 26, 2026
0011a97
Merge feat/h3-adaln-gate-residual into feat/h3-final-adaln-out
fusheng-ji Oct 26, 2026
2db1bfd
Merge feat/h3-timestep-sinusoid into feat/h3-timestep-mlp-fp32
fusheng-ji Oct 26, 2026
dab2f16
Merge feat/h3-timestep-mlp-fp32 into feat/h3-adaln-projection-3mod
fusheng-ji Oct 26, 2026
10d2671
Merge feat/h3-adaln-projection-3mod into feat/h3-adaln-row-gather
fusheng-ji Oct 26, 2026
edfa5ab
Merge feat/h3-adaln-row-gather into feat/h3-rmsnorm
fusheng-ji Oct 26, 2026
9c9ab15
Merge feat/h3-rmsnorm into feat/h3-adaln-gate-residual
fusheng-ji Oct 26, 2026
09c670b
Merge feat/h3-adaln-gate-residual into feat/h3-final-adaln-out
fusheng-ji Oct 26, 2026
07d3199
fix(h3): count every output in the bitwise heatmap and keep results w…
fusheng-ji Oct 26, 2026
92175db
fix(h3): refuse a random-weight MLP evidence run before measuring
fusheng-ji Oct 26, 2026
7bb3092
docs(h3): parameterize the sinusoid numerics and say which commits wr…
fusheng-ji Oct 26, 2026
9099084
fix(h3): refuse the projection op below SM80 and state the activation…
fusheng-ji Oct 26, 2026
5447c59
Merge feat/h3-timestep-sinusoid into feat/h3-timestep-mlp-fp32
fusheng-ji Oct 26, 2026
31aee9a
Merge feat/h3-timestep-mlp-fp32 into feat/h3-adaln-projection-3mod
fusheng-ji Oct 26, 2026
e08e5e8
Merge feat/h3-adaln-projection-3mod into feat/h3-adaln-row-gather
fusheng-ji Oct 26, 2026
9ed5d9c
fix(h3): reject indices on another device than temb, pre-SM80 devices…
fusheng-ji Oct 26, 2026
6bb1849
Merge feat/h3-adaln-row-gather into feat/h3-rmsnorm
fusheng-ji Oct 26, 2026
0f67234
fix(h3): bound-check the RMSNorm modulation row and the row-gather ba…
fusheng-ji Oct 26, 2026
669513d
fix(h3): keep the gate-residual forward out of the timed backward
fusheng-ji Oct 26, 2026
8e5ae90
Merge feat/h3-rmsnorm into feat/h3-adaln-gate-residual
fusheng-ji Oct 26, 2026
e5318ad
fix(h3): do not ask for the checkpoint when the gate-residual evidenc…
fusheng-ji Oct 26, 2026
e6ee932
test(h3): give the stubbed MLP accuracy a weight source
fusheng-ji Oct 26, 2026
223a706
Merge feat/h3 parent (#485) into #486
fusheng-ji Oct 26, 2026
c8e3eb4
Merge feat/h3 parent (#486) into #487
fusheng-ji Oct 26, 2026
7ed723a
Merge feat/h3 parent (#487) into #488
fusheng-ji Oct 26, 2026
174a7e1
Merge parent (#488) into #489
fusheng-ji Oct 26, 2026
0f66d75
fix(h3): do not consume the weight registers of columns past n_out
fusheng-ji Oct 26, 2026
1e5764e
Merge feat/h3-timestep-mlp-fp32 into feat/h3-adaln-projection-3mod
fusheng-ji Oct 26, 2026
4a1cee4
Merge parent (#485) into #486
fusheng-ji Oct 26, 2026
02531af
Merge parent (#486) into #487
fusheng-ji Oct 26, 2026
4cde743
Merge parent (#487) into #488
fusheng-ji Oct 26, 2026
5e0775b
Merge parent (#488) into #489
fusheng-ji Oct 26, 2026
c0b4cd8
fix(build): decide the H3 sources and bindings from one predicate, an…
fusheng-ji Oct 26, 2026
50f1511
Merge feat/h3-timestep-sinusoid into feat/h3-timestep-mlp-fp32
fusheng-ji Oct 26, 2026
0e911be
fix(h3): fail at build time or with a clear error when det_linear lau…
fusheng-ji Oct 26, 2026
4d691df
Merge feat/h3-timestep-mlp-fp32 into feat/h3-adaln-projection-3mod
fusheng-ji Oct 26, 2026
42455bc
Merge feat/h3-adaln-projection-3mod into feat/h3-adaln-row-gather
fusheng-ji Oct 26, 2026
f2f51f3
fix(h3): state the position contract of the gather backward and the n…
fusheng-ji Oct 26, 2026
bb4b784
Merge feat/h3-adaln-row-gather into feat/h3-rmsnorm
fusheng-ji Oct 26, 2026
fb72001
fix(h3): check the position repeat count in the modulated RMSNorm bac…
fusheng-ji Oct 26, 2026
37f54db
Merge feat/h3-rmsnorm into feat/h3-adaln-gate-residual
fusheng-ji Oct 26, 2026
3682e65
Merge feat/h3-adaln-gate-residual into feat/h3-final-adaln-out
fusheng-ji Oct 26, 2026
239ef80
fix(h3): assert the gate row in the native kernels and check the back…
fusheng-ji Oct 26, 2026
1d26287
fix(h3): check the position repeat in final_adaln_out backward and ke…
fusheng-ji Oct 26, 2026
a2d0674
docs(h3): gate-residual latencies from the backward-only rerun
fusheng-ji Oct 26, 2026
70c3d19
Merge feat/h3-adaln-gate-residual into feat/h3-final-adaln-out
fusheng-ji Oct 26, 2026
337ee60
docs(h3): final_adaln_out latencies from the backward-only rerun
fusheng-ji Oct 26, 2026
2caf0c8
fix(h3): read every spelling of relaxed nvcc math, and keep sinusoid …
fusheng-ji Oct 26, 2026
10e96ff
Merge feat/h3-timestep-sinusoid into feat/h3-timestep-mlp-fp32
fusheng-ji Oct 26, 2026
e1274b0
docs(h3): state the K and N tail contract of det_linear next to the l…
fusheng-ji Oct 26, 2026
6ab7cf2
Merge feat/h3-timestep-mlp-fp32 into feat/h3-adaln-projection-3mod
fusheng-ji Oct 26, 2026
ca14fad
fix(h3): check the SM80 requirement of the BF16 forward for the devic…
fusheng-ji Oct 26, 2026
1adec04
fix(h3): report a w1 that is not a matrix as a dimension error, and s…
fusheng-ji Oct 26, 2026
8537ecc
Merge feat/h3-timestep-mlp-fp32 into feat/h3-adaln-projection-3mod
fusheng-ji Oct 26, 2026
9c9789f
fix(h3): keep the bitwise-reuse report when a reference lacks a case,…
fusheng-ji Oct 26, 2026
2ef5b80
Merge feat/h3-adaln-projection-3mod into feat/h3-adaln-row-gather
fusheng-ji Oct 26, 2026
c416a10
fix(h3): check the row-gather tile metadata in one pre-pass, time the…
fusheng-ji Oct 26, 2026
7a5181e
Merge feat/h3-adaln-row-gather into feat/h3-rmsnorm
fusheng-ji Oct 26, 2026
3e4c849
fix(h3): check the rmsnorm table layout and tile metadata, scan rows …
fusheng-ji Oct 26, 2026
d46cbe5
Merge feat/h3-rmsnorm into feat/h3-adaln-gate-residual
fusheng-ji Oct 26, 2026
1857fa6
fix(h3): check the gate backward's tile metadata and lengths, and sca…
fusheng-ji Oct 26, 2026
9cde909
Merge feat/h3-adaln-gate-residual into feat/h3-final-adaln-out
fusheng-ji Oct 26, 2026
fcf0a58
fix(h3): run the final AdaLN backward only for the inputs that need a…
fusheng-ji Oct 26, 2026
86d6f11
docs(h3): row-gather backward timings measured without the forward pass
fusheng-ji Oct 26, 2026
8dc79df
Merge feat/h3-adaln-row-gather into feat/h3-rmsnorm
fusheng-ji Oct 26, 2026
53ba838
Merge feat/h3-rmsnorm into feat/h3-adaln-gate-residual
fusheng-ji Oct 26, 2026
1703afc
Merge feat/h3-adaln-gate-residual into feat/h3-final-adaln-out
fusheng-ji Oct 26, 2026
ac225c7
fix(build): read nvcc options files, say why a build left the H3 kern…
fusheng-ji Oct 27, 2026
9db3759
Merge feat/h3-timestep-sinusoid into feat/h3-timestep-mlp-fp32
fusheng-ji Oct 27, 2026
2ee5abc
fix(h3): skip the MLP bias fold when no bias needs a gradient, and pi…
fusheng-ji Oct 27, 2026
ffc8173
Merge feat/h3-timestep-mlp-fp32 into feat/h3-adaln-projection-3mod
fusheng-ji Oct 27, 2026
984f287
fix(h3): fail closed on a device the probe cannot query, skip the pro…
fusheng-ji Oct 27, 2026
3493f03
Merge feat/h3-adaln-projection-3mod into feat/h3-adaln-row-gather
fusheng-ji Oct 27, 2026
65e8620
fix(h3): check that the gather segments cut the tile list exactly, an…
fusheng-ji Oct 27, 2026
951bdc3
Merge feat/h3-adaln-row-gather into feat/h3-rmsnorm
fusheng-ji Oct 27, 2026
5601118
fix(h3): bound the sizes the rmsnorm kernels take as int, check the m…
fusheng-ji Oct 27, 2026
2084242
Merge feat/h3-rmsnorm into feat/h3-adaln-gate-residual
fusheng-ji Oct 27, 2026
ab407b3
fix(h3): reject gate tables whose rows overlap, and state the residua…
fusheng-ji Oct 27, 2026
0923904
Merge feat/h3-adaln-gate-residual into feat/h3-final-adaln-out
fusheng-ji Oct 27, 2026
562d3fa
fix(h3): read quoted options-file names as nvcc does, fail closed on …
fusheng-ji Oct 27, 2026
a1594ae
Merge #483 round-5 fixes into #484
fusheng-ji Oct 27, 2026
084c6a7
Merge #484 round-5 fixes into #485
fusheng-ji Oct 27, 2026
b5113d1
Merge #485 round-5 fixes into #486
fusheng-ji Oct 27, 2026
e366ece
fix(h3): require the segment tiles to partition the positions in order
fusheng-ji Oct 27, 2026
c75a8d3
Merge #486 round-5 fixes into #487
fusheng-ji Oct 27, 2026
2164211
fix(h3): reject a missing shift, scale or index in the modulated RMSNorm
fusheng-ji Oct 27, 2026
d20d767
Merge #487 round-5 fixes into #488
fusheng-ji Oct 27, 2026
60e7785
fix(h3): return no residual gradient for a residual that needs none
fusheng-ji Oct 27, 2026
b58b112
Merge #488 round-5 fixes into #489
fusheng-ji Oct 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions benchmarks/models/benchmark_h3_conditioning.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) 2026 RL-Kernel Contributors

"""Benchmark the MiniMax-H3 conditioning ops (RFC #420) against the provider path.

CUDA-event medians, bandwidth and peak memory per case, plus the backend
the registry dispatched. Timings alternate candidate/provider execution order;
backward timings exclude forward setup. Cases live in ``rl_engine/validation/models/h3_report.py``.

python benchmarks/models/benchmark_h3_conditioning.py --op timestep_sinusoid_h3
python benchmarks/models/benchmark_h3_conditioning.py --op all --json out.json
"""

from __future__ import annotations

import argparse
import json
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parents[2]))

import torch # noqa: E402

from rl_engine.runtime.registry import KernelRegistry # noqa: E402
from rl_engine.validation.models.h3_chain import environment # noqa: E402
from rl_engine.validation.models.h3_report import PERF_CASES, TIMED_KEYS, measure # noqa: E402


def main() -> None:
"""Benchmark selected CUDA operators, print summaries, and optionally save JSON."""

parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--op", default="all", choices=["all", *PERF_CASES])
parser.add_argument("--warmup", type=int, default=20)
parser.add_argument("--iters", type=int, default=200)
parser.add_argument("--json", type=Path, default=None)
args = parser.parse_args()
if not torch.cuda.is_available():
raise SystemExit("needs a CUDA device")
torch.backends.cuda.matmul.allow_tf32 = False

registry = KernelRegistry()
env = environment()
print(f"device={env['gpu']} torch={env['torch']} cuda={env['cuda']}")
print("timing order alternates each iteration; backward timings exclude forward setup")
results = []
for name in list(PERF_CASES) if args.op == "all" else [args.op]:
for case in PERF_CASES[name](registry):
row = measure(case, args.warmup, args.iters)
results.append(row)
parts = [
f"{key}={row[f'{key}_us']:.2f}us ({row[f'{key}_gbps']:.1f} GB/s, "
f"peak {row[f'{key}_peak_mib']:.2f} MiB)"
for key in TIMED_KEYS
if f"{key}_us" in row
]
order = row["execution_order"]
phases = [" -> ".join(order[f"iteration_{i}"]) for i in (0, 1)]
print(
f"{name} {row['case']} [{row['backend']}]: "
+ "; ".join(parts)
+ "; alternating order: "
+ " / ".join(phases)
)
if args.json is not None:
args.json.write_text(json.dumps({"environment": env, "results": results}, indent=2) + "\n")


if __name__ == "__main__":
main()
181 changes: 180 additions & 1 deletion build_tools/extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

import importlib.util
import os
import shlex
import stat
import sysconfig
import warnings
from distutils.errors import CompileError
Expand All @@ -14,6 +16,164 @@

_PROJECT_ROOT = Path(__file__).resolve().parents[1]

# MiniMax-H3 (RFC #420) kernels promise bitwise parity with diffusers' eager
# FP32 math. --use_fast_math swaps expf/sinf/cosf/rsqrtf and division for
# approximations and flushes denormals, so these sources are left out of
# KERNEL_ALIGN_USE_FAST_MATH=1 builds; their bindings are gated on
# KERNEL_ALIGN_WITH_H3_KERNELS and dispatch falls back to the PyTorch reference.
H3_BITWISE_SOURCES = (
"csrc/cuda/h3/timestep_sinusoid.cu",
"csrc/cuda/h3/det_linear.cu",
"csrc/cuda/h3/adaln_row_gather.cu",
"csrc/cuda/h3/rmsnorm_modulate.cu",
"csrc/cuda/h3/gate_residual.cu",
)
H3_KERNELS_DEFINE = "-DKERNEL_ALIGN_WITH_H3_KERNELS"
# nvcc options that relax FP32 math. They can also arrive through the environment, where PyTorch's
# BuildExtension appends them after the flags built here, so the H3 kernels check for them too.
# nvcc takes ``--ftz``, ``--prec-div`` and ``--prec-sqrt`` with a value, as ``--opt=value`` or
# ``--opt value``, and accepts one or two leading dashes; ``--use_fast_math`` takes none. nvcc only
# takes true / false for them and stops on ``--ftz 1``; 1 / 0 are listed too, so that a spelling
# nvcc rejects is never read as the safe one.
_RELAXED_MATH_FLAG = "use_fast_math"
_RELAXED_MATH_VALUE_FLAGS = {
"ftz": {"true", "1"},
"prec-div": {"false", "0"},
"prec-sqrt": {"false", "0"},
}
# The spelling that keeps the math exact. A value that is neither this nor in the set above is one
# nvcc does not know; it is reported as unreadable, not taken for the safe one.
_EXACT_MATH_VALUES = {"ftz": "false", "prec-div": "true", "prec-sqrt": "true"}
# An options file is read in full before anything checks it; a device node or a huge file named by
# a stray variable would hang or exhaust memory the configure step.
_OPTIONS_FILE_MAX_BYTES = 1 << 20
# nvcc reads more options from the files named by ``--options-file`` / ``-optf`` (a comma-separated
# list, as ``--options-file=a,b`` or ``--options-file a,b``), also when the option comes from
# NVCC_*_FLAGS. nvcc 13.0 does not expand ``@file`` (it takes it for an input file and stops); that
# spelling is read as well, so a driver that does expand it is covered.
_OPTIONS_FILE_FLAGS = {"optf", "options-file"}
_OPTIONS_FILE_DEPTH = 4


class _UncheckableFlags(Exception):
"""The flags cannot be read well enough to say whether they relax math."""


def _nvcc_flag_words(text: str) -> list[str]:
"""Split like nvcc does for the double-quoted values it accepts, and on ``;`` as well.

``;`` separates the flags of TORCH_NVCC_FLAGS; here it separates words outside quotes only, so
``--options-file "my opts;1.txt"`` keeps its file name in one piece, as nvcc reads it.
"""

lexer = shlex.shlex(text, posix=True)
lexer.whitespace_split = True
lexer.whitespace += ";"
lexer.commenters = ""
return list(lexer)


def _read_options_file(name: str) -> str:
path = Path(name)
try:
info = path.stat() # a missing file is an OSError, reported as unreadable
if not stat.S_ISREG(info.st_mode):
raise _UncheckableFlags(f"options file {name!r} is not a regular file")
if info.st_size > _OPTIONS_FILE_MAX_BYTES:
raise _UncheckableFlags(
f"options file {name!r} is larger than {_OPTIONS_FILE_MAX_BYTES} bytes"
)
return path.read_text()
except OSError as exc:
raise _UncheckableFlags(f"cannot read options file {name!r}: {exc.strerror}") from exc


def _nvcc_flag_tokens(text: str, *, depth: int = 0) -> list[str]:
"""Split an NVCC_*_FLAGS value into tokens, expanding options files.

A word that holds whitespace or ``;`` came out of quotes; nvcc takes it as one argument (an
option it then rejects, or a file name). It is kept whole for that reading, and its pieces
follow it, so ``"-O2 --use_fast_math"`` in one quoted word still reads as relaxed. Raises
_UncheckableFlags for an options file that cannot be read or an option nvcc rejects for lack
of its file name, and ValueError for a string that cannot be split.
"""

words = _nvcc_flag_words(text)
tokens: list[str] = []
i = 0
while i < len(words):
token = words[i]
i += 1
files: list[str]
if token.startswith("@"):
files = [token[1:]]
elif token.startswith("-") and token.lstrip("-").partition("=")[0] in _OPTIONS_FILE_FLAGS:
_, has_value, value = token.lstrip("-").partition("=")
if not has_value:
if i >= len(words) or words[i].startswith("-"):
raise _UncheckableFlags(f"{token} has no file name")
value = words[i]
i += 1
files = value.split(",")
else:
tokens.append(token)
pieces = token.replace(";", " ").split()
if len(pieces) > 1:
tokens.extend(pieces)
continue
if depth >= _OPTIONS_FILE_DEPTH:
raise _UncheckableFlags(f"options files nest deeper than {_OPTIONS_FILE_DEPTH} levels")
for name in files:
tokens.extend(_nvcc_flag_tokens(_read_options_file(name), depth=depth + 1))
return tokens


def _tokens_relax_math(tokens: list[str]) -> str | None:
"""Return the first option that relaxes FP32 math, spelled as given, or None."""

for i, token in enumerate(tokens):
if not token.startswith("-"):
continue
name, has_value, value = token.lstrip("-").partition("=")
if name == _RELAXED_MATH_FLAG:
return token
relaxed_values = _RELAXED_MATH_VALUE_FLAGS.get(name)
if relaxed_values is None:
continue
spelled = token
if not has_value:
# "--ftz true": the value is the next word. Without one, nvcc rejects the option; treat
# it as relaxed rather than guess.
nxt = tokens[i + 1] if i + 1 < len(tokens) else ""
if nxt.startswith("-") or not nxt:
return f"{token} without a value"
value = nxt
spelled = f"{token} {nxt}"
if value.lower() in relaxed_values:
return spelled
if value.lower() != _EXACT_MATH_VALUES[name]:
return f"{spelled} (a value nvcc does not take)"
return None
Comment on lines +152 to +156

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bug · high
_tokens_relax_math fails open on a value flag whose spelling nvcc rejects or reinterprets. --ftz=1 is handled only because 1 is listed, but --ftz=yes, --prec-div=maybe, or --prec-div=FALSE (uppercase is fine via .lower(), but --prec-div=no) fall through value.lower() in relaxed_values and return None, so _relaxed_math_reason() reports nothing and the H3 kernels are compiled with the define while an options string that relaxes (or that nvcc will reject) is in effect. The docstring of _relaxed_math_reason promises to fail closed on values it cannot parse; anything that is neither the safe spelling (false/true per flag) nor the relaxed set should be reported as uncheckable rather than treated as safe.

Suggestion:

Suggested change
if value.lower() in relaxed_values:
return spelled
return None
if value.lower() in relaxed_values:
return spelled
if value.lower() not in _SAFE_RELAXED_MATH_VALUES[name]:
return f"{spelled} (unrecognised value)"
return None

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 562d3fa. A value of --ftz / --prec-div / --prec-sqrt that is neither the relaxed spelling nor the exact one (false / true / true) is now reported (... contains --ftz=yes (a value nvcc does not take)), so the H3 kernels are left out of such a build instead of being kept on the strength of a flag nobody parsed. nvcc itself stops on those values, so no such build compiled with them, but the predicate no longer reads them as safe. Upper-case spellings of the real values (--ftz=FALSE) are still read as exact. --prec-div=no and the others are in the new test_values_nvcc_does_not_take_are_not_read_as_the_exact_spelling.



def _relaxed_math_reason() -> str | None:
"""Say why NVCC_*_FLAGS / TORCH_NVCC_FLAGS turn on relaxed FP32 math, or None if they do not.

Fails closed: a value that cannot be parsed or an options file that cannot be read gives a
reason too, because the H3 kernels would otherwise be built with flags nobody checked.
"""

for name in ("NVCC_PREPEND_FLAGS", "NVCC_APPEND_FLAGS", "TORCH_NVCC_FLAGS"):
try:
relaxed = _tokens_relax_math(_nvcc_flag_tokens(os.environ.get(name, "")))
except ValueError as exc:
return f"{name} cannot be parsed ({exc})"
except _UncheckableFlags as exc:
return f"{name}: {exc}"
if relaxed is not None:
return f"{name} contains {relaxed}"
return None


def _resolve_package_data_source(
filename: str | os.PathLike[str],
Expand Down Expand Up @@ -219,6 +379,20 @@ def get_extensions():
)

if is_rocm or torch.cuda.is_available():
use_fast_math = envs.env_flag(envs.KERNEL_ALIGN_USE_FAST_MATH)
# One predicate decides both the H3 sources and the define that enables their bindings, so
# the bindings can never outlive the kernels.
relaxed_reason = _relaxed_math_reason()
relaxed_math_env = relaxed_reason is not None
if relaxed_math_env and not is_rocm:
warnings.warn(
f"NVCC_*_FLAGS / TORCH_NVCC_FLAGS relax FP32 math or cannot be checked "
f"({relaxed_reason}); the bitwise MiniMax-H3 kernels are left out of this build "
"and dispatch falls back to the PyTorch reference.",
RuntimeWarning,
stacklevel=2,
)
h3_enabled = not is_rocm and not use_fast_math and not relaxed_math_env

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bug · high
The relaxed-math gate inspects only NVCC_PREPEND_FLAGS/NVCC_APPEND_FLAGS/TORCH_NVCC_FLAGS, but PyTorch's BuildExtension does not use all of them the same way. In particular TORCH_NVCC_FLAGS is only consumed when torch.utils.cpp_extension falls into its _get_cuda_arch_flags-less path (no NVCC_APPEND_FLAGS); and torch also honours NVCC_PREPEND_FLAGS/NVCC_APPEND_FLAGS plus the flags in os.environ['NVCC_FLAGS']-adjacent paths and CUDA_HOME-derived nvcc wrappers. More importantly, the predicate never sees -Xcompiler/nvcc flags that reach the compiler via TORCH_CUDA_ARCH_LIST-style options files or via the CC/CXX/NVCC wrapper scripts. If any of those paths introduces --use_fast_math/--ftz=true, neither this function nor the docs' claim that the extension "is built without --use_fast_math" holds: h3_enabled stays True and the H3 kernels are compiled with relaxed math while their bindings are exported. Since nvcc exposes no in-source macro, there is no second line of defence.

If the intent is to cover exactly these three variables, that contract should be stated (and documented) rather than implied; additionally TORCH_NVCC_FLAGS should be checked with the separator torch actually uses (;), which _nvcc_flag_words does globally, so a TORCH_NVCC_FLAGS='-optf a.opts;b.opts' is read as two separate words rather than one comma list — worth confirming against torch's parsing.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not changed. nvcc does not read CFLAGS, CXXFLAGS or CPPFLAGS: with all three set to --use_fast_math --ftz=true --prec-div=false, nvcc --dryrun on a division kernel prints none of those options, same as with no variables set (checked with nvcc 13.0). The channels it does read are NVCC_PREPEND_FLAGS, NVCC_APPEND_FLAGS and, through the torch build, TORCH_NVCC_FLAGS; _relaxed_math_reason() covers those, including --options-file/-optf files named in them. -Xcompiler, -Xptxas and -Xcudafe pass options to the host compiler, ptxas and the front end and do not change -ftz or -prec-div, which are cicc options. The ; separator of TORCH_NVCC_FLAGS is handled by the lexer (; is a separator, quoted words stay whole) and the tests added in 562d3fa3 cover it.

cuda_sources = [
"csrc/bindings/ops.cpp",
"csrc/cuda/logprob/fused_logp_kernel.cu",
Expand All @@ -241,12 +415,14 @@ def get_extensions():
# CUDA IPC and the fixed-tree collective implementation are not
# part of the ROCm extension.
cuda_sources.append("csrc/cuda/collectives/deterministic_collective.cu")
if h3_enabled:
cuda_sources.extend(H3_BITWISE_SOURCES)
# This source contains NVIDIA PTX (cp.async, ldmatrix, and mma.sync).
# The ROCm dispatcher falls back to PyTorch SDPA for this operator.
cuda_sources.append("csrc/cuda/attention/prefix_shared_attention.cu")

nvcc_flags = ["-O3", "-Xfatbin", "-compress-all"]
if envs.env_flag(envs.KERNEL_ALIGN_USE_FAST_MATH):
if use_fast_math:
nvcc_flags.append("--use_fast_math")
if not is_rocm:
cc_major, cc_minor = torch.cuda.get_device_capability()
Expand Down Expand Up @@ -333,6 +509,9 @@ def get_extensions():
if os.name != "nt" and not is_rocm:
# CUDA IPC metadata queries use the driver API (cuPointerGetAttribute).
extra_link_args.append("-lcuda")
if h3_enabled:
cxx_flags.append(H3_KERNELS_DEFINE)
nvcc_flags.append(H3_KERNELS_DEFINE)

if not is_rocm:
sm90_srcs = [
Expand Down
83 changes: 83 additions & 0 deletions csrc/bindings/ops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,46 @@ at::Tensor prefix_shared_attention(
#endif
#endif

// MiniMax-H3 (RFC #420) conditioning-path declarations. CUDA only.
// Fast-math builds omit the H3 sources (bitwise contract), so gate on the build define.
#if defined(KERNEL_ALIGN_WITH_H3_KERNELS)
torch::Tensor h3_timestep_sinusoid_forward(torch::Tensor timestep, int64_t num_channels,
double max_period, bool check_range);
std::vector<torch::Tensor> h3_det_linear_forward(torch::Tensor x, torch::Tensor weight,
c10::optional<torch::Tensor> bias,
int64_t activation, bool save_pre_activation);
torch::Tensor h3_det_linear_backward_input(torch::Tensor grad, torch::Tensor weight,
c10::ScalarType out_dtype);
std::vector<torch::Tensor> h3_det_linear_backward_weight(torch::Tensor grad, torch::Tensor x,
c10::ScalarType w_dtype,
bool with_bias);
torch::Tensor h3_adaln_row_gather_forward(torch::Tensor rows, torch::Tensor timestep_indices,
torch::Tensor token_tags, int64_t chunks,
int64_t modality_num);
torch::Tensor h3_adaln_row_gather_backward(torch::Tensor grad, torch::Tensor sorted_pos,
torch::Tensor tile_begin, torch::Tensor tile_end,
torch::Tensor seg_first_tile,
c10::ScalarType out_dtype);
std::vector<torch::Tensor> h3_rmsnorm_forward(torch::Tensor x, torch::Tensor weight, double eps,
c10::optional<torch::Tensor> shift,
c10::optional<torch::Tensor> scale,
c10::optional<torch::Tensor> index);
std::vector<torch::Tensor> h3_rmsnorm_backward(
torch::Tensor grad, torch::Tensor x, torch::Tensor weight, torch::Tensor rstd,
c10::optional<torch::Tensor> shift, c10::optional<torch::Tensor> scale,
c10::optional<torch::Tensor> index, c10::optional<torch::Tensor> sorted_pos,
c10::optional<torch::Tensor> tile_begin, c10::optional<torch::Tensor> tile_end,
c10::optional<torch::Tensor> seg_first_tile);
torch::Tensor h3_gate_residual_forward(torch::Tensor residual, torch::Tensor y, torch::Tensor gate,
torch::Tensor index);
std::vector<torch::Tensor> h3_gate_residual_backward(torch::Tensor grad, torch::Tensor y,
torch::Tensor gate, torch::Tensor index,
torch::Tensor sorted_pos,
torch::Tensor tile_begin,
torch::Tensor tile_end,
torch::Tensor seg_first_tile);
#endif

// PyBind11 Module Registration
PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
m.doc() = "RL-Kernel High-Performance Operator Extension Library";
Expand Down Expand Up @@ -758,4 +798,47 @@ PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
"Deterministic GPT-NeoX token-major RoPE apply for ROCm");
#endif
#endif

#if defined(KERNEL_ALIGN_WITH_H3_KERNELS)
m.def("h3_timestep_sinusoid_forward", torch::wrap_pybind_function(h3_timestep_sinusoid_forward),
Comment on lines +802 to +803

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bug · critical
These H3 registrations are committed to the rl_engine._C module, but build_tools/extensions.py only compiles the H3 sources (H3_BITWISE_SOURCES) and defines KERNEL_ALIGN_WITH_H3_KERNELS for the separate rl_engine._H3_C extension (see the if h3_flags: block that builds _H3_C from csrc/bindings/h3_ops.cpp). Consequences:

  1. In a normal build the define is never set for the _C TU, so this whole block is compiled out and rl_engine._C.h3_* never exists — every caller that only checks hasattr(_C, "h3_...") (e.g. timestep_sinusoid.py, det_linear.py) permanently falls back to the reference path, and the documented kernel IDs (docs/operators/h3-timestep-sinusoid.md lists rl_engine._C.h3_timestep_sinusoid_forward) are unreachable.
  2. If the define were ever propagated to the _C build (the comment says it should be gated solely on fast-math), _C would fail to link because the H3 .cu definitions are not in cuda_sources for _C.

Suggest registering these ops in the _H3_C module (where the sources and define already live) and exposing them via a separate _H3_C handle, or aligning the build so the define and the H3 sources are added to the same extension that hosts these bindings.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not changed: the premise does not hold. rl_engine._H3_C is the separate attention extension (csrc/bindings/h3_ops.cpp binds h3_attention_* only). The H3 sources (H3_BITWISE_SOURCES) and -DKERNEL_ALIGN_WITH_H3_KERNELS are both added to rl_engine._C (build_tools/extensions.py, cuda_sources.extend(H3_BITWISE_SOURCES) and the two cxx_flags/nvcc_flags.append(H3_KERNELS_DEFINE) lines) under the same h3_enabled predicate, so the bindings in ops.cpp exist exactly when the kernels were compiled into the same library. In a normal build rl_engine._C.h3_timestep_sinusoid_forward, h3_det_linear_*, h3_adaln_row_gather_*, h3_rmsnorm_* and h3_gate_residual_* are all present (the H3 tests that skip without them run and pass on B200), and the build test asserts that the sources and the define appear together and disappear together under KERNEL_ALIGN_USE_FAST_MATH=1 and under relaxed flags from the environment.

"MiniMax-H3 FP32 [cos | sin] timestep features, bitwise to the diffusers CUDA path",
py::arg("timestep"), py::arg("num_channels") = 256, py::arg("max_period") = 10000.0,
py::arg("check_range") = true);
m.def("h3_det_linear_forward", &h3_det_linear_forward,
"Batch-invariant warp-per-column linear (contract h3-det-linear-v1), optional SiLU",
py::arg("x"), py::arg("weight"), py::arg("bias") = py::none(),
py::arg("activation") = 0, py::arg("save_pre_activation") = false);
m.def("h3_det_linear_backward_input", &h3_det_linear_backward_input,
"Deterministic grad @ weight with fixed 64-row N chunks folded in order",
py::arg("grad"), py::arg("weight"), py::arg("out_dtype"));
m.def("h3_det_linear_backward_weight", &h3_det_linear_backward_weight,
"Deterministic dW/dbias as ascending-row FP32 folds",
py::arg("grad"), py::arg("x"), py::arg("w_dtype"), py::arg("with_bias") = true);
m.def("h3_adaln_row_gather_forward", &h3_adaln_row_gather_forward,
"Fused six-way AdaLN row gather by timestep_index * 3 + token_tag (pure copy)",
py::arg("rows"), py::arg("timestep_indices"), py::arg("token_tags"),
py::arg("chunks") = 6, py::arg("modality_num") = 3);
m.def("h3_adaln_row_gather_backward", &h3_adaln_row_gather_backward,
"Deterministic segmented sum (sorted tiles folded in order) for the row gather",
py::arg("grad"), py::arg("sorted_pos"), py::arg("tile_begin"), py::arg("tile_end"),
py::arg("seg_first_tile"), py::arg("out_dtype"));
m.def("h3_rmsnorm_forward", &h3_rmsnorm_forward,
"RMSNorm replaying PyTorch's reduction order, with optional fused AdaLN modulation",
py::arg("x"), py::arg("weight"), py::arg("eps"), py::arg("shift") = py::none(),
py::arg("scale") = py::none(), py::arg("index") = py::none());
m.def("h3_rmsnorm_backward", &h3_rmsnorm_backward,
"Deterministic RMSNorm(+modulation) backward: row-local dx, tiled dweight, sorted table grads",
py::arg("grad"), py::arg("x"), py::arg("weight"), py::arg("rstd"),
py::arg("shift") = py::none(), py::arg("scale") = py::none(),
py::arg("index") = py::none(), py::arg("sorted_pos") = py::none(),
py::arg("tile_begin") = py::none(), py::arg("tile_end") = py::none(),
py::arg("seg_first_tile") = py::none());
m.def("h3_gate_residual_forward", &h3_gate_residual_forward,
"residual + gate[index] * y with the gate row gathered in-kernel (eager rounding order)",
py::arg("residual"), py::arg("y"), py::arg("gate"), py::arg("index"));
m.def("h3_gate_residual_backward", &h3_gate_residual_backward,
"Gated-residual backward: exact dy, deterministic sorted segment sum for dgate",
py::arg("grad"), py::arg("y"), py::arg("gate"), py::arg("index"), py::arg("sorted_pos"),
py::arg("tile_begin"), py::arg("tile_end"), py::arg("seg_first_tile"));
#endif
}
Loading
Loading