Repository navigation
feat(hiptensor): add bf16 support for elementwise permute - #14406
Merged
Merged
Conversation
✅ All Checks Passed — Ready for Review
📖 Need help? See the Policy FAQ for details on every check and how to fix failures. |
|
🎉 All checks passed! This PR is ready for review. |
1 task done
Ryker0627
reviewed
Oct 28, 2026
Ryker0627
reviewed
Oct 28, 2026
Ryker0627
approved these changes
Oct 28, 2026
Ryker0627
left a comment
Contributor
There was a problem hiding this comment.
This is a well-executed PR. The registration and test-config coverage are complete, and the documentation is accurate. You can ignore the two minor comments.
evedovelli
added a commit
that referenced
this pull request
Oct 29, 2026
…ary (#14564) ## Motivation Elementwise binary accepts six data type combinations: f16, bf16, f32 and f64, with f16 and bf16 also allowed an f32 scalar. Trinary only accepted f16, f32 and f64 with a same-type scalar. Binary's bf16 and f16-with-f32-scalar paths were also accepted by the API but never tested end to end; no test config used them. This PR gives trinary the same support as binary and tests all six combinations for both ops. Stacked on the elementwise-test refactor PR; retarget to `develop` after it merges. ISSUE ID : AIHIPTENS-589 ## Technical Details **Library** - `hiptensor_elementwise_trinary.cpp`: the type table adds `{16F,16F,16F,32F}`, `{16BF,16BF,16BF,16BF}` and `{16BF,16BF,16BF,32F}` (typeA, typeB, typeC, typeScalar), matching binary. - `hiptensorElementwiseTrinaryExecute` now returns `HIPTENSOR_STATUS_NOT_SUPPORTED` when D's data type differs from C's, as binary already does. Previously the mismatch failed later with `HIPTENSOR_STATUS_INTERNAL_ERROR`. - `elementwise_trinary_solution_rank{2..6}_half_instances.cpp`: register `ck::Tuple<bhalf_t, bhalf_t, bhalf_t>` alongside half, as the binary half files already do. - No new op code: trinary uses the same `HiptensorBinaryOp` and `UnaryCombinedOp` that binary bf16 already compiles with. - The trinary kernel parameters and fallback hashes are type-generic. - The CPU reference already registered bf16 trinary. - Trinary scalars are read with `readVal<float>`, which handles a bf16 compute descriptor since #14406. **Tests** - Binary and trinary harnesses: `checkDevice` accepts bf16 (gated on `isF16Supported()`). Scalar writes, comparison and printing already go through the type-dispatch helper from the refactor PR. - Configs, binary and trinary, ranks 2-6: | Category | Entries added | |---|---| | `validation/quick`, `emulation/quick` | `[16BF,16BF]` | | `validation/standard`, `emulation/full`, `bench` | `[16F,32F]`, `[16BF,16BF]`, `[16BF,32F]` | `validation/comprehensive` and `validation/full` stay empty for these ops, as before. - `elementwise_cpu_test`: three new cases each for binary and trinary: bf16, bf16 with an f32 scalar, and f16 with an f32 scalar. The shared helpers use explicit casts so they compile for `hip_bfloat16`; f32 and f16 values are unchanged. - `elementwise_mode_test`: `TrinaryWithMismatchedOutputTypeReturnsNotSupported`. It uses f16 for D so it runs on GPUs without FP64. **Docs** - `api-reference.rst`: the old "Element-wise Operations" rows (`f16 / f32 / -` etc.) are replaced by one "Element-wise (Permutation, binary, trinary)" group. All three ops now support the same six combinations. A new note says that for element-wise ops all tensors share one data type and the compute type is the scalar type. - `installation.rst`: binary and trinary test descriptions include bfloat16. - `CHANGELOG.md` (2.6.0): Added (trinary bf16, and f16 with an f32 scalar); Changed (trinary output-type check). - `TESTING.md`: binary, trinary, CPU-reference and mode-test rows updated; the "binary BF16 untested" known gap removed. ## Test Plan Built with `-DGPU_TARGETS=<arch>` and run on real hardware: - `ctest -R 'elementwise|util_test'` (21 tests). - `elementwise_cpu_test` and `elementwise_mode_test` directly. - Binary and trinary binaries, ranks 2-6, default (`validation/standard`) config, counting validated cases per type pair. - Rank 3 with the `emulation/full` and `bench` configs (bench with validation off). ## Test Result | Arch | binary + trinary, all type pairs, ranks 2-6 | `elementwise_cpu_test` | `elementwise_mode_test` | ctest | |---|---|---|---|---| | gfx942 (MI300A) | 6 pairs pass | 15/15 | 13/13 | 21/21 | | gfx950 (MI350X) | 6 pairs pass | 15/15 | 13/13 | 21/21 | | gfx90a (MI210) | 6 pairs pass | 15/15 | 13/13 | 21/21 | | gfx908 (MI100) | 5 pairs pass (no FP64) | 14, FP64 skipped | 13/13 | 21/21 | | gfx1201 | 5 pairs pass (no FP64) | 14, FP64 skipped | 13/13 | 21/21 | ## Submission Checklist - [x] Look over the contributing guidelines at https://github.com/ROCm/TheRock/blob/main/GOVERNANCE.md#pull-requests.
Contributor
TheRock Submodule Bump ActivityNewest first
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
hiptensorPermutesupports f16, f32 and f64 but rejects bf16, even though the binary elementwise op already registers bf16 and the CK ops used by permute (Scale,PassThrough,HiptensorUnaryOp) all havebhalf_toverloads. The CPU reference already registers bf16 permute for ranks 2-6, so only the device path, type validation and tests were missing.While adding this, I found that the
readVal(void const*, hiptensorComputeDescriptor_t)overload has noHIPTENSOR_COMPUTE_DESC_16BFcase and returns 0. A bf16 scalar would have been silently treated as 0 on both the GPU and CPU-reference sides, so GPU-vs-CPU tests could not catch it. The same bug already affects two shipped APIs:hiptensorElementwiseBinaryExecutewith a bf16 scalar type (alpha, gamma).hiptensorReducewith a bf16 compute type (alpha, beta). Its existing bf16-compute test cases were comparing all-zero outputs.The PR also fills test-coverage gaps for f64 permute (from #13081) that turned up during review.
ISSUE ID : AIHIPTENS-296
Technical Details
hiptensor_elementwise_permute.cpp): adds{R_16BF, R_16BF}and{R_16BF, R_32F}. Also fixes the table comment, whose columns aretypeA, typeScalar.hiptensor_elementwise_permute.cpp):hiptensorPermutenow also requires the output tensor's data type to match the input's, as the binary op already does for C and D. Previously a mismatch (e.g. bf16 in, f32 out) passed validation and failed later withHIPTENSOR_STATUS_INTERNAL_ERROR("Selected kernel is unable to solve the problem"). It now returnsHIPTENSOR_STATUS_NOT_SUPPORTED.elementwise_permute_solution_rank{2..6}_bhalf{,_noop}_instances.cpp, registeringck::Tuple<ck::bhalf_t>with the existingCkPermutationUnaryCombinedOpandCkPermutationPassThroughCombinedOp. No new op struct is needed: CKScale<bhalf_t, bhalf_t>multiplies in float with a float scale.GetInstances, ranks 2-4 reuse the double branches (256/64/64/4/4, vector width 4 with 2 and 1 as fallbacks). The matching fallback hashes are added ininstance_params.cpp. Untuned, as for f64. Ranks 5-6 use the existing type-generic branch. The tuned selection tables have noR_16BFkeys, so lookup falls back to the default parameters, which are registered.readValfix (data_types_impl.hpp): adds theHIPTENSOR_COMPUTE_DESC_16BFcase. This overload is used by the elementwise ops (permute, binary, trinary) and by reduction (hiptensorReduceand its CPU reference). Contraction uses theScalarDataspecialization and is not affected.elementwise_test.cpp/elementwise_resource.cpp:checkDevice, gated onisF16Supported()as in reduction._Float16.compareEqualLaunchKernel<hip_bfloat16>.util_test:readValComputeDescTest(fails before the fix).elementwise_mode_test:PermutationWithMismatchedOutputTypeReturnsNotSupportedcovers item 2.elementwise_cpu_test: new permute cases that compare the CPU reference against hard-coded expected values:CompareBF16ResultWithReference: bf16 scalar of 2.1. Also a regression test for thereadValfix.CompareBF16WithF32ScalarResultWithReference: bf16 data with an f32 scalar.CompareF64ResultWithReference: expected values and alpha kept in double, with a 1e-12 tolerance, so a float-precision regression (about 1e-8) fails. It is skipped withGTEST_SKIP()on GPUs without FP64. Without that, creating the f64 descriptor returnsARCH_MISMATCHand ctest would skip the whole binary there.The shared helper now uses explicit casts so it compiles for
hip_bfloat16; f32 and f16 are unchanged.test/utils.hpp:compareEqualno longer truncatesdoublevalues to float. This also tightens the f64 comparison inreduction_cpu_impl_test, which still passes.Permutation configs, ranks 2-6:
validation/quick,emulation/quick[16BF,16BF]validation/standard,validation/comprehensive[16BF,16BF],[16BF,32F]emulation/full[64F,64F],[16BF,16BF],[16BF,32F]bench[16BF,16BF],[16BF,32F],[64F,64F](f64 last, see below)validation/fullstays empty because it inherits the lower tiers.emulation/fullgets its own entries becauseffm-fulldoes not inherit fromffm-quick.emulation/quick, which has bf16;test/02_elementwise/configs/code_coverage/is not used for elementwise.CHANGELOG.md, under 2.6.0:hiptensorElementwiseBinaryExecuteandhiptensorReduce.TESTING.md:batched_contraction_test,elementwise_mode_test,elementwise_broadcast_test,elementwise_output_strides_test).emulation/full,bench, CPU-reference case).Test Plan
Built with
-DGPU_TARGETS=<arch>and run on real hardware:ctest -R 'elementwise|util_test|reduction'(28 tests).elementwise_cpu_test,elementwise_mode_testandreduction_cpu_impl_testdirectly.emulation/fullandbenchconfigs (bench with validation off, as in CI).validation/standard) configs, which include bf16 compute.Test Result
Final head (all fixes), plus the reduction suite:
elementwise_cpu_testelementwise_mode_testPermute data-type coverage from the earlier rounds:
emulation/full, bench)emulation/full, bench)emulation/fullpass; bench ranks 2 and 4 run out of memory*emulation/fullpass; bench ranks 3, 5, 6*emulation/fullpass; bench ranks 3, 5*gfx942 is not validated at the final head. On the only gfx942 node available,
rank1_reduction_testpassed 48/48 and then hung in the GPU driver during process exit (uninterruptible,synchronize_srcu). That is a node issue, not a test failure, but the remaining reduction ranks and the review fixes did not run on gfx942.* Bench out-of-memory failures (documented in
TESTING.mdKnown Gaps):Known gaps / follow-ups (not addressed here)
readValpart of the binary fix is covered byutil_test.PermutationTest::RunKernelare near-identical copies; a templated helper would remove the duplication.Submission Checklist