diff --git a/ext/ArrayInterfaceCUDAExt.jl b/ext/ArrayInterfaceCUDAExt.jl index 715f8107..7ba6216a 100644 --- a/ext/ArrayInterfaceCUDAExt.jl +++ b/ext/ArrayInterfaceCUDAExt.jl @@ -3,6 +3,7 @@ module ArrayInterfaceCUDAExt using ArrayInterface using CUDA using CUDA.CUSOLVER +using CUDA.CUSPARSE using LinearAlgebra function ArrayInterface.lu_instance(A::CuMatrix{T}) where {T} @@ -13,6 +14,17 @@ end ArrayInterface.device(::Type{<:CUDA.CuArray}) = ArrayInterface.GPU() +# CUSPARSE arrays implement no `setindex!` at all, so the `true` default is wrong +# for them and callers guarding mutation with `can_setindex` hit a CanonicalIndexError. +const CuSparseArray = Union{ + CUSPARSE.CuSparseVector, + CUSPARSE.CuSparseMatrixCSC, + CUSPARSE.CuSparseMatrixCSR, + CUSPARSE.CuSparseMatrixBSR, + CUSPARSE.CuSparseMatrixCOO, +} +ArrayInterface.can_setindex(::Type{<:CuSparseArray}) = false + function ArrayInterface.promote_eltype( ::Type{<:CUDA.CuArray{T, N, M}}, ::Type{T2} ) where {T, N, M, T2} diff --git a/test/gpu/cuda.jl b/test/gpu/cuda.jl index 2651a638..b60c356e 100644 --- a/test/gpu/cuda.jl +++ b/test/gpu/cuda.jl @@ -18,3 +18,11 @@ lu_sparse = lu!(lu_inst_sparse, A_sparse) #test that the resulting lu works b = CuVector([1f0, 1f0]) @test CUDA.@allowscalar lu_sparse \ b == [1, 1] + +# CUSPARSE arrays have no `setindex!`, so `can_setindex` must not claim they do +@test ArrayInterface.can_setindex(A_dense) +@test !ArrayInterface.can_setindex(A_sparse) +@test !ArrayInterface.can_setindex(CuSparseMatrixCSC(sparse(A_cpu))) +@test !ArrayInterface.can_setindex(CuSparseMatrixCOO(sparse(A_cpu))) +@test !ArrayInterface.can_setindex(CuSparseVector(sparsevec([1], [1.0f0], 2))) +@test_throws CanonicalIndexError A_sparse[1, 2] = 1.0f0