Improve the performance of qr_ks_vs_whole_k_prefetch pipeline - #6209
Conversation
git-subtree-dir: projects/composablekernel git-subtree-split: d9ecf29860e21fb3eeeadeae973c985313b2c597
…composablekernel'
…_gemm_areg_bsmem_trload_creg_v2_prefetch_n.hpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…ock_fmha_pipeline_qr_ks_vs_whole_k_prefetch.hpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…ock_fmha_pipeline_qr_ks_vs_whole_k_prefetch_default_policy.hpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…ock_fmha_pipeline_qr_ks_vs_whole_k_prefetch_trload.hpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…_asserts for trload and dropout protection Agent-Logs-Url: https://github.com/ROCm/rocm-libraries/sessions/1e1fbad9-d6e9-4e76-a2b5-3e8764dfe304 Co-authored-by: poyenc <1132573+poyenc@users.noreply.github.com>
Agent-Logs-Url: https://github.com/ROCm/rocm-libraries/sessions/1e1fbad9-d6e9-4e76-a2b5-3e8764dfe304 Co-authored-by: poyenc <1132573+poyenc@users.noreply.github.com>
…etNumPrefetchV, fix typo Agent-Logs-Url: https://github.com/ROCm/rocm-libraries/sessions/4e1a9bcd-0097-4dbf-87e2-24475d122caa Co-authored-by: poyenc <1132573+poyenc@users.noreply.github.com>
Agent-Logs-Url: https://github.com/ROCm/rocm-libraries/sessions/4e1a9bcd-0097-4dbf-87e2-24475d122caa Co-authored-by: poyenc <1132573+poyenc@users.noreply.github.com>
…sert from GetSmemSizeDropout, revert grammar changes Agent-Logs-Url: https://github.com/ROCm/rocm-libraries/sessions/82852c64-4aa0-46b4-bc6e-2c5f21b06f1e Co-authored-by: poyenc <1132573+poyenc@users.noreply.github.com>
|
This PR is a re-submit of PR-6087 |
|
@copilot Can you transfer the comments history from PR 6087 to current PR ? |
…d pipeline_problem include in default policy Agent-Logs-Url: https://github.com/ROCm/rocm-libraries/sessions/b4df152f-fcfd-432e-82da-eca42ac0d6be Co-authored-by: qianfengz <12429178+qianfengz@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR enhances the qr_ks_vs_whole_k_prefetch FMHA forward pipeline for improved GPU occupancy and performance (notably on MI350) by introducing an N0-loop formulation, updated GEMM micro-kernels/policies, and an additional trload-based V-loading pipeline variant.
Changes:
- Added new block GEMM variants to support N- and K-prefetch schemes, including a transposed-load (trload) B path for V GEMM.
- Reworked the whole-K-prefetch FMHA pipeline to use an N0-loop (kN0 subdivided by kK0) and to support non-power-of-two head dims (e.g., 96/160) without padding.
- Updated the FMHA forward kernel to support “naive head-dim load”, optional FAST_EXP2 bypass, and a trload V path, plus plumbing for
seqstart_v_scale_ptr.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| projects/composablekernel/include/ck_tile/ops/gemm/block/block_gemm_areg_bsmem_trload_creg_v2_prefetch_n.hpp | New GEMM kernel variant supporting transposed B loads with N-prefetch. |
| projects/composablekernel/include/ck_tile/ops/gemm/block/block_gemm_areg_bsmem_creg_v2_prefetch_n.hpp | New GEMM kernel variant implementing N-prefetch. |
| projects/composablekernel/include/ck_tile/ops/gemm/block/block_gemm_areg_bsmem_creg_v2_prefetch_k.hpp | New GEMM kernel variant implementing K-prefetch. |
| projects/composablekernel/include/ck_tile/ops/fmha/pipeline/tile_fmha_shape.hpp | Minor formatting and static_assert message update. |
| projects/composablekernel/include/ck_tile/ops/fmha/pipeline/block_fmha_pipeline_qs_ks_vs.hpp | Extends pipeline operator signature to accept sink_v (ignored). |
| projects/composablekernel/include/ck_tile/ops/fmha/pipeline/block_fmha_pipeline_qr_ks_vs_whole_k_prefetch.hpp | Major pipeline rewrite: N0-loop, changed K/V LDS usage, revised softmax flow. |
| projects/composablekernel/include/ck_tile/ops/fmha/pipeline/block_fmha_pipeline_qr_ks_vs_whole_k_prefetch_trload.hpp | New trload-based whole-K-prefetch pipeline to avoid shuffle overhead. |
| projects/composablekernel/include/ck_tile/ops/fmha/pipeline/block_fmha_pipeline_qr_ks_vs_whole_k_prefetch_default_policy.hpp | Reworked policy: new GEMM selection, new LDS descriptors/layout, KV shared LDS sizing. |
| projects/composablekernel/include/ck_tile/ops/fmha/pipeline/block_fmha_pipeline_problem.hpp | Adds vector-size helpers for DRAM tile access decisions. |
| projects/composablekernel/include/ck_tile/ops/fmha/kernel/fmha_fwd_kernel.hpp | Adds pipeline feature detection (n0loop/fast-exp2/naive-hdim/trload), updates Q/K/V window padding and scale behavior. |
| projects/composablekernel/include/ck_tile/ops/fmha.hpp | Wires in the new whole-K-prefetch trload pipeline header. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| constexpr auto c_block_dstr_encode = detail::make_embed_tile_distribution_encoding( | ||
| c_block_outer_dstr_encoding, typename WG::CWarpDstrEncoding{}); | ||
|
|
||
| // constrcut from A-block-tensor from A-Block-tensor-tmp |
There was a problem hiding this comment.
Typo in comment: “constrcut” → “construct”.
| // constrcut from A-block-tensor from A-Block-tensor-tmp | |
| // construct from A-block-tensor from A-Block-tensor-tmp |
| constexpr auto c_block_dstr_encode = detail::make_embed_tile_distribution_encoding( | ||
| c_block_outer_dstr_encoding, typename WG::CWarpDstrEncoding{}); | ||
|
|
||
| // constrcut from A-block-tensor from A-Block-tensor-tmp |
There was a problem hiding this comment.
Typo in comment: “constrcut” → “construct”.
| // constrcut from A-block-tensor from A-Block-tensor-tmp | |
| // construct from A-block-tensor from A-Block-tensor-tmp |
Here is a summary of the review comments from PR #6087 transferred to this PR: Review comments from PR #60871.
2.
3.
4.
5.
6.
7.
8. Wrong type args in
9.
10. Typo fixes
|
…ock_fmha_pipeline_qr_ks_vs_whole_k_prefetch_default_policy.hpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…ity in both whole_k_prefetch pipelines Agent-Logs-Url: https://github.com/ROCm/rocm-libraries/sessions/890bd16b-d92f-47fa-850f-6249ac94df75 Co-authored-by: qianfengz <12429178+qianfengz@users.noreply.github.com>
poyenc
left a comment
There was a problem hiding this comment.
Thanks for the performance work — the numbers for kM0=64 shapes are impressive (20-30% gains). A few items to address:
Blocking
1. Early-exit guard removed from the pipeline
The do { ... } while(seqlen_k_curr < seqlen_k_end) loop in block_fmha_pipeline_qr_ks_vs_whole_k_prefetch.hpp always executes at least once, even when seqlen_k_start >= seqlen_k_end. The previous version had an early-exit check. Without it, the first iteration will load K/V tiles from invalid ranges when there's zero work (masking or padded seqlen_k cases). Please re-add the guard:
if constexpr(FmhaMask::IsMasking || kPadSeqLenK)
{
if(seqlen_k_start >= seqlen_k_end)
return o_acc;
}2. kIsAvailable guard removed without replacement
The kernel's operator() now unconditionally calls run_(). On non-gfx950 targets, load_tile_transpose silently returns zeros (see buffer_view.hpp:897 fallback). The old if constexpr(kIsAvailable) guard prevented this silent data corruption. Please add a compile-time guard in the trload pipeline, e.g.:
#if !defined(__gfx950__)
static_assert(sizeof(QDataType) == 0,
"whole_k_prefetch_trload requires gfx950; "
"load_tile_transpose returns zeros on other architectures.");
#endifSuggestions
3. Pipeline-specific if constexpr in the kernel
The 4 new SFINAE trait detectors (is_n0loop_pipeline_v, is_naive_hdim_load_v, is_using_trload_v, ignore_fast_exp2_v) add 8 if constexpr branches into fmha_fwd_kernel.hpp, coupling the kernel to pipeline internals. Consider exposing these as direct constants on the pipeline type instead of SFINAE detection:
// Each pipeline defines directly:
static constexpr index_t kN0ForKView = ...;
static constexpr index_t kHeaddimForQKView = ...;
static constexpr bool kTransformScaleS = ...;This eliminates the detail namespace machinery and makes future pipelines easier to add without touching the kernel.
4. kIgnoreFastExp2 needs a comment
This is a new concept with non-obvious correctness implications. A brief comment at the definition site explaining why it's safe (softmax is base-invariant) would help future readers.
Nits
5. }; // namespace detail → } // namespace detail (two locations — fmha_fwd_kernel.hpp, block_fmha_pipeline_problem.hpp). Zero precedent for ; in ck_tile/.
6. static_assert(NWarp == 1, "Check failed!") in block_gemm_areg_bsmem_creg_v2_prefetch_k.hpp — please use a descriptive message.
7. #if 0 dead code in block_gemm_areg_bsmem_creg_v2_prefetch_k.hpp — the sibling files (prefetch_n, trload_prefetch_n) already cleaned this up. Please remove and keep only a one-line comment about the register spill issue.
…s not bigger than seqlen_k_start
…led on arch other than gfx950
|
poyenc
left a comment
There was a problem hiding this comment.
All blocking and correctness items from the prior review are addressed. The remaining open items (SFINAE refactor, assert message) are non-blocking style/maintainability suggestions that can be tackled separately.
|
Override merge due to test failure on previous mici run reporting after a pass on latest run. |
Improve the performance of qr_ks_vs_whole_k_prefetch pipeline (#6209) ## About qr_ks_vs_whole_k_prefetch pipeline This PR updates and enhances the qr_ks_vs_whole_k_prefetch pipeline to improve performance on both MI350 GPUs through better MFMA instruction usage, transposed V-loading support, and N0-loop implementation. The pipeline targets scenarios where the number of workgroups is low, enabling better CU occupancy by using smaller MTile sizes (kM0=64 vs 128) while prefetching entire K tiles. ## Changes: - Adds transposed V-loading support (qr_ks_vs_whole_k_prefetch_trload) to avoid using shuffle instructions on MI350 - Implements N0-loop based Gemm0 to reduce tile window movement overhead and eliminate `clear_tile` calls - Adds full support for hdim96/hdim160 without padding requirements - Updates MFMA instruction selection to ensure optimal choices for MI350 ## Performance results 1. For attention shapes which leads to kM0=64, `qr_ks_vs_async_whole_k_prefetch_trload` shows much better performance than `qr_ks_vs_async_trload` on the same case (execution time `41.02ms` by whole_k_prefetch_trload & `58.50ms` by async_load), and `qr_ks_vs_async_whole_k_prefetch_trload` also shows obviously better performance than the recently tuned `qr_ks_vs_async` on the same case (execution time `41.02ms` by whole_k_prefetch_trload 7 `47.60ms` by qr_ks_vs_async) 2. Also on MI300, for attention shapes which leads to kM0=64, `qr_ks_vs_async_whole_k_prefetch` shows much better performance than the `qr_ks_vs_async` (which is supposed to be very high-efficient) on the same case (execution time `64.50ms` by whole_k_prefetch & `80.20ms` by qr_ks_vs_async) 3. For attention shapes which leads to kM0=128, `qr_ks_vs_async_whole_k_prefetch_trload` show a little bit better performance than `qr_ks_vs_async` on mi350 (execution time `104.50ms` by whole_k_prefetch_trload & `106.50ms` by qr_ks_vs_async). And they shows completely on-par performance on MI300 ## Test/Verify 1. Use the ROCM xformers branch `test_whole_k_prefetch_n0loop` to test/verify qr_ks_vs_whole_k_prefetch pipeline since this pipeline can not be used by ck_tile fmha example so far 2. Use the following command-line for building/testing xformers >```bash > #> git clone -b test_whole_k_prefetch_n0loop https://github.com/ROCm/xformers > #> git submodule update --init --recursive > #> pip install --no-build-isolation -e ./ > #> pytest tests/test_mem_eff_attention.py::test_forward >``` 4. Any scripts which can run on xformers can be used to evaluate qr_ks_vs_whole_k_prefetch pipeline. Using the two environ variable to switch from using different pipelines > ```bash > #> export FMHA_DISABLE_SPECIAL_TREATMENT=1 #> to disable using FAV3 and qr_ks_vs_async_trload pipeline > #> export FMHA_ENABLE_ASYNC_PIPELINE=1 #> to disable using qr_ks_vs_async pipeline for comparing > ``` ## Discussion
Drop FA4 conditional rescaling from block_fmha_pipeline_qr_ks_vs_whole_k_prefetch.hpp. Upstream PR ROCm#6209 refactored this pipeline (renamed p_compute -> pcomp_tile, SMPLComputeDataType -> CompDataType) and set kIgnoreFastExp2 = true. With the FAST_EXP2 path disabled here, FA4's main payoff (avoiding the SW exp2 polynomial on rescale rows) no longer applies, so this resolution takes upstream's version of this file and keeps FA4 only in the other 5 FMHA pipelines.
…#6209 whole_k_prefetch conflict by taking develop's version; this pipeline opts out of FAST_EXP2 via kIgnoreFastExp2=true)
## About qr_ks_vs_whole_k_prefetch pipeline This PR updates and enhances the qr_ks_vs_whole_k_prefetch pipeline to improve performance on both MI350 GPUs through better MFMA instruction usage, transposed V-loading support, and N0-loop implementation. The pipeline targets scenarios where the number of workgroups is low, enabling better CU occupancy by using smaller MTile sizes (kM0=64 vs 128) while prefetching entire K tiles. ## Changes: - Adds transposed V-loading support (qr_ks_vs_whole_k_prefetch_trload) to avoid using shuffle instructions on MI350 - Implements N0-loop based Gemm0 to reduce tile window movement overhead and eliminate `clear_tile` calls - Adds full support for hdim96/hdim160 without padding requirements - Updates MFMA instruction selection to ensure optimal choices for MI350 ## Performance results 1. For attention shapes which leads to kM0=64, `qr_ks_vs_async_whole_k_prefetch_trload` shows much better performance than `qr_ks_vs_async_trload` on the same case (execution time `41.02ms` by whole_k_prefetch_trload & `58.50ms` by async_load), and `qr_ks_vs_async_whole_k_prefetch_trload` also shows obviously better performance than the recently tuned `qr_ks_vs_async` on the same case (execution time `41.02ms` by whole_k_prefetch_trload 7 `47.60ms` by qr_ks_vs_async) 2. Also on MI300, for attention shapes which leads to kM0=64, `qr_ks_vs_async_whole_k_prefetch` shows much better performance than the `qr_ks_vs_async` (which is supposed to be very high-efficient) on the same case (execution time `64.50ms` by whole_k_prefetch & `80.20ms` by qr_ks_vs_async) 3. For attention shapes which leads to kM0=128, `qr_ks_vs_async_whole_k_prefetch_trload` show a little bit better performance than `qr_ks_vs_async` on mi350 (execution time `104.50ms` by whole_k_prefetch_trload & `106.50ms` by qr_ks_vs_async). And they shows completely on-par performance on MI300 ## Test/Verify 1. Use the ROCM xformers branch `test_whole_k_prefetch_n0loop` to test/verify qr_ks_vs_whole_k_prefetch pipeline since this pipeline can not be used by ck_tile fmha example so far 2. Use the following command-line for building/testing xformers >```bash > #> git clone -b test_whole_k_prefetch_n0loop https://github.com/ROCm/xformers > #> git submodule update --init --recursive > #> pip install --no-build-isolation -e ./ > #> pytest tests/test_mem_eff_attention.py::test_forward >``` 4. Any scripts which can run on xformers can be used to evaluate qr_ks_vs_whole_k_prefetch pipeline. Using the two environ variable to switch from using different pipelines > ```bash > #> export FMHA_DISABLE_SPECIAL_TREATMENT=1 #> to disable using FAV3 and qr_ks_vs_async_trload pipeline > #> export FMHA_ENABLE_ASYNC_PIPELINE=1 #> to disable using qr_ks_vs_async pipeline for comparing > ``` ## Discussion --------- Co-authored-by: Po Yen Chen <PoYen.Chen@amd.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: poyenc <1132573+poyenc@users.noreply.github.com> Co-authored-by: qianfengz <12429178+qianfengz@users.noreply.github.com> Co-authored-by: Illia Silin <98187287+illsilin@users.noreply.github.com>
Improve the performance of qr_ks_vs_whole_k_prefetch pipeline (#6209) ## About qr_ks_vs_whole_k_prefetch pipeline This PR updates and enhances the qr_ks_vs_whole_k_prefetch pipeline to improve performance on both MI350 GPUs through better MFMA instruction usage, transposed V-loading support, and N0-loop implementation. The pipeline targets scenarios where the number of workgroups is low, enabling better CU occupancy by using smaller MTile sizes (kM0=64 vs 128) while prefetching entire K tiles. ## Changes: - Adds transposed V-loading support (qr_ks_vs_whole_k_prefetch_trload) to avoid using shuffle instructions on MI350 - Implements N0-loop based Gemm0 to reduce tile window movement overhead and eliminate `clear_tile` calls - Adds full support for hdim96/hdim160 without padding requirements - Updates MFMA instruction selection to ensure optimal choices for MI350 ## Performance results 1. For attention shapes which leads to kM0=64, `qr_ks_vs_async_whole_k_prefetch_trload` shows much better performance than `qr_ks_vs_async_trload` on the same case (execution time `41.02ms` by whole_k_prefetch_trload & `58.50ms` by async_load), and `qr_ks_vs_async_whole_k_prefetch_trload` also shows obviously better performance than the recently tuned `qr_ks_vs_async` on the same case (execution time `41.02ms` by whole_k_prefetch_trload 7 `47.60ms` by qr_ks_vs_async) 2. Also on MI300, for attention shapes which leads to kM0=64, `qr_ks_vs_async_whole_k_prefetch` shows much better performance than the `qr_ks_vs_async` (which is supposed to be very high-efficient) on the same case (execution time `64.50ms` by whole_k_prefetch & `80.20ms` by qr_ks_vs_async) 3. For attention shapes which leads to kM0=128, `qr_ks_vs_async_whole_k_prefetch_trload` show a little bit better performance than `qr_ks_vs_async` on mi350 (execution time `104.50ms` by whole_k_prefetch_trload & `106.50ms` by qr_ks_vs_async). And they shows completely on-par performance on MI300 ## Test/Verify 1. Use the ROCM xformers branch `test_whole_k_prefetch_n0loop` to test/verify qr_ks_vs_whole_k_prefetch pipeline since this pipeline can not be used by ck_tile fmha example so far 2. Use the following command-line for building/testing xformers >```bash > #> git clone -b test_whole_k_prefetch_n0loop https://github.com/ROCm/xformers > #> git submodule update --init --recursive > #> pip install --no-build-isolation -e ./ > #> pytest tests/test_mem_eff_attention.py::test_forward >``` 4. Any scripts which can run on xformers can be used to evaluate qr_ks_vs_whole_k_prefetch pipeline. Using the two environ variable to switch from using different pipelines > ```bash > #> export FMHA_DISABLE_SPECIAL_TREATMENT=1 #> to disable using FAV3 and qr_ks_vs_async_trload pipeline > #> export FMHA_ENABLE_ASYNC_PIPELINE=1 #> to disable using qr_ks_vs_async pipeline for comparing > ``` ## Discussion --------- Co-authored-by: Po Yen Chen <PoYen.Chen@amd.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: poyenc <1132573+poyenc@users.noreply.github.com> Co-authored-by: qianfengz <12429178+qianfengz@users.noreply.github.com> Co-authored-by: Illia Silin <98187287+illsilin@users.noreply.github.com>
About qr_ks_vs_whole_k_prefetch pipeline
This PR updates and enhances the qr_ks_vs_whole_k_prefetch pipeline to improve performance on both MI350 GPUs through better MFMA instruction usage, transposed V-loading support, and N0-loop implementation. The pipeline targets scenarios where the number of workgroups is low, enabling better CU occupancy by using smaller MTile sizes (kM0=64 vs 128) while prefetching entire K tiles.
Changes:
clear_tilecallsPerformance results
qr_ks_vs_async_whole_k_prefetch_trloadshows much better performance thanqr_ks_vs_async_trloadon the same case (execution time41.02msby whole_k_prefetch_trload &58.50msby async_load), andqr_ks_vs_async_whole_k_prefetch_trloadalso shows obviously better performance than the recently tunedqr_ks_vs_asyncon the same case (execution time41.02msby whole_k_prefetch_trload 747.60msby qr_ks_vs_async)qr_ks_vs_async_whole_k_prefetchshows much better performance than theqr_ks_vs_async(which is supposed to be very high-efficient) on the same case (execution time64.50msby whole_k_prefetch &80.20msby qr_ks_vs_async)qr_ks_vs_async_whole_k_prefetch_trloadshow a little bit better performance thanqr_ks_vs_asyncon mi350 (execution time104.50msby whole_k_prefetch_trload &106.50msby qr_ks_vs_async). And they shows completely on-par performance on MI300Test/Verify
test_whole_k_prefetch_n0loopto test/verify qr_ks_vs_whole_k_prefetch pipeline since this pipeline can not be used by ck_tile fmha example so farDiscussion