Repository navigation
Make device min/max propagate NaNs and order signed zeros - #1148
Merged
Merged
Conversation
Move compile_offline out of the atomic metadata testset so that other codegen tests can compile for GPUs other than the local one too.
Base.min/max on Float16/32/64 were overridden with ocml's min/max, which return the other operand when one is NaN and, like llvm.minnum/maxnum, leave the result for -0 and +0 unspecified. Julia's min/max propagate NaNs and treat -0 as smaller than +0, so kernels computed different results than the host, which also leaked into Atomix's CAS-loop atomic min/max. With LLVM 19+ (Julia 1.13+), use the same llvm.minimum/maximum intrinsics as Base, which LLVM expands for every AMDGPU target. Older LLVM versions can't lower them in general (the reason Julia 1.12 needs the FastMath workaround), so use an explicit comparison-based implementation there. Fixes #1142
Contributor
AMDGPU.jl BenchmarksDetails
This comment was automatically generated by workflow using github-action-benchmark. |
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.
Stacked on #1147 (merge that first).
On the device,
Base.min/Base.maxfor Float16/32/64 were overridden with ocml'smin/max, which ignore NaN operands and leave the result for −0/+0 unspecified. Julia'smin/maxpropagate NaNs and treat −0 as smaller than +0, so e.g.max(NaN32, 1f0)returned1f0in a kernel. This also affected@atomic max/minon floats, which on Julia ≤ 1.13 is a compare-exchange loop aroundBase.max/min, while Julia 1.14 lowers it toatomicrmw fmaximum, so results depended on the Julia version.With Julia's LLVM 19 or later (Julia 1.13+), the overrides now emit
llvm.minimum/llvm.maximum, like Base; LLVM expands these for every AMDGPU target and has native instructions on gfx12. Older LLVM versions can't lower those intrinsics in general (hence the existing Julia 1.12 FastMath workaround), so there the overrides use a comparison-based implementation. The choice is made from Julia's LLVM version, so this also applies with the external back-end. The fallback costs a few extra instructions: on gfx1036 with Julia 1.12, a Float32maxbecomes four compares and a select, versusv_max_f32+v_cmp_o_f32+ select withllvm.maximumon Julia 1.13.Tests compare device results against the host for NaN in either or both operands, ±0 in both orders, infinities and subnormals (Float16/32/64), check atomic min/max with NaNs, and check offline codegen for gfx90a/gfx942/gfx1200 with both back-ends. Tested locally on gfx1036 with Julia 1.12 and 1.13 (external back-end), and before rebasing onto #1147 also with Julia 1.14-DEV and the in-process back-end; not on Julia 1.10/1.11.
Fixes #1142