diff --git a/ext/RecursiveArrayToolsCUDAExt.jl b/ext/RecursiveArrayToolsCUDAExt.jl index 950bf709..cc52a1de 100644 --- a/ext/RecursiveArrayToolsCUDAExt.jl +++ b/ext/RecursiveArrayToolsCUDAExt.jl @@ -1,6 +1,6 @@ module RecursiveArrayToolsCUDAExt -using RecursiveArrayTools: AbstractVectorOfArray +using RecursiveArrayTools: AbstractVectorOfArray, ArrayPartition import CUDA: CuArray # Disambiguate CuArray(::AbstractVectorOfArray) vs CuArray(::AbstractArray{T,N}) from CUDA.jl. @@ -10,4 +10,12 @@ function CuArray(VA::AbstractVectorOfArray{T, N}) where {T, N} return CuArray{T, N}(stack(VA.u)) end +# Assemble each state from its GPU partitions before stacking the states. +# Stacking ArrayPartitions directly reads their elements on the CPU. +function CuArray( + VA::AbstractVectorOfArray{T, N, <:AbstractVector{<:ArrayPartition}} + ) where {T, N} + return CuArray{T, N}(stack(map(ap -> vcat(vec.(ap.x)...), VA.u))) +end + end diff --git a/test/GPU/vectorofarray_gpu.jl b/test/GPU/vectorofarray_gpu.jl index b5bf351f..a14a68b2 100644 --- a/test/GPU/vectorofarray_gpu.jl +++ b/test/GPU/vectorofarray_gpu.jl @@ -52,3 +52,20 @@ _b = Adapt.adapt(CuArray, b) @test _b isa DiffEqArray @test _b.u isa Vector{<:CuArray} @test _b.t isa CuArray + +# Conversion of partitioned solution states must stay on the GPU. +states = [ + ArrayPartition(CUDA.fill(1.0f0, 2), CUDA.fill(2.0f0, 3)), + ArrayPartition(CUDA.fill(3.0f0, 2), CUDA.fill(4.0f0, 3)), +] +partitioned_sol = DiffEqArray(states, Float32[0, 1]) +partitioned_cu = CuArray(partitioned_sol) +@test partitioned_cu isa CuArray +@test size(partitioned_cu) == (5, 2) +@test Array(partitioned_cu) == Float32[1 3; 1 3; 2 4; 2 4; 2 4] + +matrix_states = [ + ArrayPartition(CUDA.fill(1.0f0, 2, 2), CUDA.fill(2.0f0, 1)), + ArrayPartition(CUDA.fill(3.0f0, 2, 2), CUDA.fill(4.0f0, 1)), +] +@test Array(CuArray(VectorOfArray(matrix_states))) == Float32[1 3; 1 3; 1 3; 1 3; 2 4]