Repository navigation
Support arrays of isbits unions - #735
Merged
Merged
Conversation
oneArray rejected element types like `Union{Int,Nothing}` or
`Union{Missing,Bool}`, although the device side already knew how to load
and store them. Store them like `Array` does: the data, padded to
`aligned_sizeof` per element, followed by one selector byte per element.
`maxsize` locates an array's selector bytes. Derived arrays advance it by
their element offset, which the byte offset can't recover for unions of
singletons, so kernels on views of these arrays use the view's own
selector bytes. Every copy path (to and from the host, between device
arrays, and through host pointers into shared and host memory) and
`resize!` copy the selector bytes too; scalar indexing of host-accessible
arrays goes through such a copy, and `unsafe_wrap(Array, ...)` rejects
unions as an `Array` keeps its selector bytes elsewhere.
On the device, `Const` arrays (used by AcceleratedKernels' reductions)
load unions through their selector byte. Structs with a union field took
the union path too, reading a selector byte past the end of the array;
they keep their selector inside the element, and now load as plain bits.
This was referenced Oct 23, 2026
Closed
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #735 +/- ##
==========================================
+ Coverage 85.08% 85.60% +0.51%
==========================================
Files 53 52 -1
Lines 4660 4550 -110
==========================================
- Hits 3965 3895 -70
+ Misses 695 655 -40 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
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.
oneArray rejected isbits-union element types (
Union{Int,Nothing},Union{Missing,Bool}, ...) with "oneArray does not yet support isbits-union arrays". This adds support, following the layout and design of JuliaGPU/AMDGPU.jl#1182 (see also JuliaGPU/AMDGPU.jl#1171).Layout is the same as
Array's: the data,aligned_sizeof(T)bytes per element, followed by one selector byte per element. The device side already had the union load/store code; what was missing is on the host:maxsizelocates an array's selector bytes.GPUArrays.deriveadvances it by the element offset, since the byte offset can't recover that for unions of singletons (Union{Nothing,Missing}), and kernels getmaxsize - offsetso that views use their own selector bytes.resize!. Union uploads aren't staged (they synchronize instead), as the selector bytes would need a staged copy of their own.unsafe_load;unsafe_wrap(Array, ...)rejects unions.Constarrays (which AcceleratedKernels' reductions use) load unions through their selector byte, and structs with a union field no longer take the union path, which read a selector byte past the end of the array.aligned_sizeof, which differs fromsizeoffor e.g.Union{Int64,NTuple{3,Int32}}(16 vs. 12 bytes). On Julia 1.10 it's wrapped in a@generatedfunction, asBase.aligned_sizeofdoesn't fold to a constant in device code there.This also enables the union tests in GPUArrays' testsuite (
reinterpretof a union array,any/allonUnion{Missing,Bool}), which check for support at run time.Not addressed: SPIRVIntrinsics'
emit_localmemorysizes local memory aslen * sizeof(T)plus the selector bytes, which is too small foroneLocalArrays of unions likeUnion{Int64,NTuple{3,Int32}}whose size isn't a multiple of their alignment.