Repository navigation
perf(ck_tile/fmha): [gfx1250 opt 3] 16-row short-query tile for the gfx1250 qr_tdm forward #13469
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a60f83a
9fb1308
402cd34
95855fd
94227a0
0d89b8b
71530c7
04ab967
b6c8dad
c98808a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1680,7 +1680,24 @@ def check_gemm0_k( | |
| return k0_loops == 1 | ||
| return k0_loops >= 2 | ||
|
|
||
| rules.extend([check_gemm0_k, check_qr_tdm_sched_codegen_compatibility]) | ||
| def check_short_query_tile( | ||
| problem_ctx: ProblemContext, kernel_ctx: KernelContext | ||
| ) -> bool: | ||
| # The 16-row tile spends its warps on N, which only qr_tdm handles: | ||
| # qr's gemm_1 slices P along M and cannot form a slice narrower than | ||
| # one warp tile, so pairing the tile with qr fails to compile. | ||
| if kernel_ctx.tile.F_bm0 != 16: | ||
| return True | ||
| return kernel_ctx.pipeline.tag == "qr_tdm" | ||
|
|
||
| # The sched rule stays last (its tests address it as get_rules()[-1]). | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment documents that Have those two tests select the rule by name or function identity instead of position, e.g. |
||
| rules.extend( | ||
| [ | ||
| check_gemm0_k, | ||
| check_short_query_tile, | ||
| check_qr_tdm_sched_codegen_compatibility, | ||
| ] | ||
| ) | ||
| return rules | ||
|
|
||
| @classmethod | ||
|
|
@@ -1716,7 +1733,11 @@ def get_hdim_tile_size_dict(cls, dtype: str) -> Optional[dict]: | |
| FmhaFwdTileSize(128, 64, 32, 64, 32, 64, 4, 1, 1, 4, 1, 1, 16, 16, 32, 16, 16, 32, -1)], | ||
| ( 96, 96) : [FmhaFwdTileSize( 64, 64, 32, 96, 32, 96, 4, 1, 1, 4, 1, 1, 16, 16, 32, 16, 16, 32, -1, _gfx125_qr_tdm_crossover_constraint(( 96, 96))), | ||
| FmhaFwdTileSize(128, 64, 32, 96, 32, 96, 4, 1, 1, 4, 1, 1, 16, 16, 32, 16, 16, 32, -1)], | ||
| (128, 128) : [FmhaFwdTileSize( 64, 64, 32, 128, 32, 128, 4, 1, 1, 4, 1, 1, 16, 16, 32, 16, 16, 32, -1, CppConstraint(m64_d128_constraint)), | ||
| # Short query (s_q <= 16): the 64-row tile would idle 3/4 of its M | ||
| # rows, so this tile spends its four warps on N instead (1,4,1). | ||
| # Listed first: dispatch takes the first tile whose constraint holds. | ||
| (128, 128) : [FmhaFwdTileSize( 16, 64, 32, 128, 32, 128, 1, 4, 1, 1, 4, 1, 16, 16, 32, 16, 16, 32, -1, CppConstraint("a.max_seqlen_q <= 16")), | ||
| FmhaFwdTileSize( 64, 64, 32, 128, 32, 128, 4, 1, 1, 4, 1, 1, 16, 16, 32, 16, 16, 32, -1, CppConstraint(m64_d128_constraint)), | ||
| FmhaFwdTileSize(128, 64, 32, 128, 32, 128, 4, 1, 1, 4, 1, 1, 16, 16, 32, 16, 16, 32, -1)], | ||
| (160, 160) : [FmhaFwdTileSize( 64, 64, 32, 160, 32, 160, 4, 1, 1, 4, 1, 1, 16, 16, 32, 16, 16, 32, -1, _gfx125_qr_tdm_crossover_constraint((160, 160))), | ||
| FmhaFwdTileSize(128, 64, 32, 160, 32, 160, 4, 1, 1, 4, 1, 1, 16, 16, 32, 16, 16, 32, -1)], | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check keys on the tile's
F_bm0dimension rather than the geometry invariant it's actually protecting. The comment above explains the real constraint:qr's gemm_1 slices P along M and can't form a slice narrower than one warp tile, which only matters when gemm_1's warps are split along N instead of M. That's exactly whatF_rn1encodes (the tile dataclass defines it as "number of warps for gemm1 along head dim v"). Today's singleF_bm0==16tile happens to be the only N-split tile, so the check works, but it only works by coincidence: a future N-split tile at a differentF_bm0would skip this guard and still fail to compile withqr, while an unrelated M-split tile that happens to useF_bm0==16would be needlessly barred fromqr.Check the actual invariant instead: