diff --git a/.github/workflows/Documentation.yml b/.github/workflows/Documentation.yml index d26b9dd03..1fce3a0cb 100644 --- a/.github/workflows/Documentation.yml +++ b/.github/workflows/Documentation.yml @@ -11,7 +11,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: julia-actions/setup-julia@latest with: version: '1' @@ -23,6 +23,6 @@ jobs: DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} # For authentication with SSH deploy key run: julia --project=docs/ --code-coverage=user docs/make.jl - uses: julia-actions/julia-processcoverage@v1 - - uses: codecov/codecov-action@v4 + - uses: codecov/codecov-action@v5 with: file: lcov.info diff --git a/.github/workflows/Downgrade.yml b/.github/workflows/Downgrade.yml new file mode 100644 index 000000000..64466aab5 --- /dev/null +++ b/.github/workflows/Downgrade.yml @@ -0,0 +1,36 @@ +name: Downgrade +on: + pull_request: + branches: + - master + paths-ignore: + - 'docs/**' + - 'benchmark/**' + push: + branches: + - master + paths-ignore: + - 'docs/**' + - 'benchmark/**' +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + downgrade_mode: ['alldeps'] + julia-version: ['1.10'] + group: ['Core'] + steps: + - uses: actions/checkout@v5 + - uses: julia-actions/setup-julia@v2 + with: + version: ${{ matrix.julia-version }} + - uses: julia-actions/julia-downgrade-compat@v2 + with: + skip: Pkg,TOML + - uses: julia-actions/julia-buildpkg@v1 + - uses: julia-actions/julia-runtest@v1 + with: + ALLOW_RERESOLVE: false + env: + GROUP: ${{ matrix.group }} diff --git a/.github/workflows/Downstream.yml b/.github/workflows/Downstream.yml index 34b8e1bca..dc09c0945 100644 --- a/.github/workflows/Downstream.yml +++ b/.github/workflows/Downstream.yml @@ -32,14 +32,14 @@ jobs: - {user: SciML, repo: DelayDiffEq.jl, group: Interface} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: julia-actions/setup-julia@v1 with: version: ${{ matrix.julia-version }} arch: x64 - uses: julia-actions/julia-buildpkg@latest - name: Clone Downstream - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: repository: ${{ matrix.package.user }}/${{ matrix.package.repo }} path: downstream @@ -61,6 +61,6 @@ jobs: exit(0) # Exit immediately, as a success end - uses: julia-actions/julia-processcoverage@v1 - - uses: codecov/codecov-action@v4 + - uses: codecov/codecov-action@v5 with: file: lcov.info diff --git a/.github/workflows/Invalidations.yml b/.github/workflows/Invalidations.yml index 28b9ce2fa..7f084d239 100644 --- a/.github/workflows/Invalidations.yml +++ b/.github/workflows/Invalidations.yml @@ -19,12 +19,12 @@ jobs: - uses: julia-actions/setup-julia@v1 with: version: '1' - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-invalidations@v1 id: invs_pr - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: ref: ${{ github.event.repository.default_branch }} - uses: julia-actions/julia-buildpkg@v1 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d9333ffbf..8d933f0f0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,8 +15,12 @@ jobs: - Core version: - '1' + os: + - ubuntu-latest + - macos-latest + - windows-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: julia-actions/setup-julia@v1 with: version: ${{ matrix.version }} @@ -35,6 +39,6 @@ jobs: env: GROUP: ${{ matrix.group }} - uses: julia-actions/julia-processcoverage@v1 - - uses: codecov/codecov-action@v4 + - uses: codecov/codecov-action@v5 with: - file: lcov.info \ No newline at end of file + file: lcov.info diff --git a/Project.toml b/Project.toml index 3dfc4a97d..df62ce433 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "ArrayInterface" uuid = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9" -version = "7.17.0" +version = "7.22.0" [deps] Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" @@ -14,6 +14,7 @@ CUDSS = "45b445bb-4962-46a0-9369-b4df9d0f772e" ChainRules = "082447d4-558c-5d27-93f4-14fc19e9eca2" ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" GPUArraysCore = "46192b85-c4d5-4398-a991-12ede77f4527" +Metal = "dde4c033-4e86-420c-a63e-0dd931031962" ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" StaticArraysCore = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" @@ -23,10 +24,11 @@ Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" ArrayInterfaceBandedMatricesExt = "BandedMatrices" ArrayInterfaceBlockBandedMatricesExt = "BlockBandedMatrices" ArrayInterfaceCUDAExt = "CUDA" -ArrayInterfaceCUDSSExt = "CUDSS" -ArrayInterfaceChainRulesExt = "ChainRules" +ArrayInterfaceCUDSSExt = ["CUDSS", "CUDA"] ArrayInterfaceChainRulesCoreExt = "ChainRulesCore" +ArrayInterfaceChainRulesExt = "ChainRules" ArrayInterfaceGPUArraysCoreExt = "GPUArraysCore" +ArrayInterfaceMetalExt = "Metal" ArrayInterfaceReverseDiffExt = "ReverseDiff" ArrayInterfaceSparseArraysExt = "SparseArrays" ArrayInterfaceStaticArraysCoreExt = "StaticArraysCore" @@ -37,12 +39,13 @@ Adapt = "4" BandedMatrices = "1" BlockBandedMatrices = "0.13" CUDA = "5" -CUDSS = "0.2, 0.3" +CUDSS = "0.6.1" ChainRules = "1" ChainRulesCore = "1" ChainRulesTestUtils = "1" GPUArraysCore = "0.1, 0.2" LinearAlgebra = "1.10" +Metal = "1" ReverseDiff = "1" SparseArrays = "1.10" StaticArraysCore = "1" @@ -59,6 +62,8 @@ ChainRulesTestUtils = "cdddcdb0-9152-4a09-a978-84456f9df70a" ComponentArrays = "b0b7db55-cfe3-40fc-9ded-d10e2dbeff66" FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b" GPUArraysCore = "46192b85-c4d5-4398-a991-12ede77f4527" +JuliaFormatter = "98e50ef6-434e-11e9-1051-2b60c6c9e899" +Metal = "dde4c033-4e86-420c-a63e-0dd931031962" Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" diff --git a/ext/ArrayInterfaceBandedMatricesExt.jl b/ext/ArrayInterfaceBandedMatricesExt.jl index fcd0fb7b0..5eaeb0cdf 100644 --- a/ext/ArrayInterfaceBandedMatricesExt.jl +++ b/ext/ArrayInterfaceBandedMatricesExt.jl @@ -46,7 +46,7 @@ function _bandsize(bandind, rowsize, colsize) end end -function BandedMatrixIndex(rowsize, colsize, lowerbandwidth, upperbandwidth, isrow) +function ArrayInterface.BandedMatrixIndex(rowsize, colsize, lowerbandwidth, upperbandwidth, isrow) upperbandwidth > -lowerbandwidth || throw(ErrorException("Invalid Bandwidths")) bandinds = upperbandwidth:-1:(-lowerbandwidth) bandsizes = [_bandsize(band, rowsize, colsize) for band in bandinds] diff --git a/ext/ArrayInterfaceCUDSSExt.jl b/ext/ArrayInterfaceCUDSSExt.jl index 01fb23953..e6a4908d2 100644 --- a/ext/ArrayInterfaceCUDSSExt.jl +++ b/ext/ArrayInterfaceCUDSSExt.jl @@ -2,14 +2,18 @@ module ArrayInterfaceCUDSSExt using ArrayInterface using CUDSS +using CUDA function ArrayInterface.lu_instance(A::CUDSS.CuSparseMatrixCSR) ArrayInterface.LinearAlgebra.checksquare(A) - fact = CudssSolver(A, "G", 'F') T = eltype(A) - n = size(A,1) - x = CudssMatrix(T, n) - b = CudssMatrix(T, n) + n = size(A, 1) + + # Use standard CUDA types (CuVector) instead of deprecated CudssMatrix + x = CUDA.CuVector{T}(undef, n) + b = CUDA.CuVector{T}(undef, n) + + fact = CudssSolver(A, "G", 'F') cudss("analysis", fact, x, b) fact end diff --git a/ext/ArrayInterfaceMetalExt.jl b/ext/ArrayInterfaceMetalExt.jl new file mode 100644 index 000000000..c27f67f24 --- /dev/null +++ b/ext/ArrayInterfaceMetalExt.jl @@ -0,0 +1,15 @@ +module ArrayInterfaceMetalExt + +using ArrayInterface +using Metal +using LinearAlgebra + +function ArrayInterface.lu_instance(A::MtlMatrix{T}) where {T} + ipiv = MtlVector{Int32}(undef, 0) + info = zero(Int) + return LinearAlgebra.LU(similar(A, 0, 0), ipiv, info) +end + +ArrayInterface.device(::Type{<:Metal.MtlArray}) = ArrayInterface.GPU() + +end # module \ No newline at end of file diff --git a/ext/ArrayInterfaceReverseDiffExt.jl b/ext/ArrayInterfaceReverseDiffExt.jl index 37176824e..3a000def3 100644 --- a/ext/ArrayInterfaceReverseDiffExt.jl +++ b/ext/ArrayInterfaceReverseDiffExt.jl @@ -8,11 +8,8 @@ ArrayInterface.ismutable(T::Type{<:ReverseDiff.TrackedReal}) = false ArrayInterface.can_setindex(::Type{<:ReverseDiff.TrackedArray}) = false ArrayInterface.fast_scalar_indexing(::Type{<:ReverseDiff.TrackedArray}) = false function ArrayInterface.aos_to_soa(x::AbstractArray{<:ReverseDiff.TrackedReal, N}) where {N} - if length(x) > 1 - return reshape(reduce(vcat, x), size(x)) - else - return reduce(vcat,[x[1], x[1]])[1:1] - end + y = length(x) > 1 ? reduce(vcat, x) : reduce(vcat, [x[1], x[1]])[1:1] + return reshape(y, size(x)) end function ArrayInterface.restructure(x::Array, y::ReverseDiff.TrackedArray) diff --git a/ext/ArrayInterfaceSparseArraysExt.jl b/ext/ArrayInterfaceSparseArraysExt.jl index 61fff69dc..9f0e06b43 100644 --- a/ext/ArrayInterfaceSparseArraysExt.jl +++ b/ext/ArrayInterfaceSparseArraysExt.jl @@ -14,25 +14,25 @@ function findstructralnz(x::SparseMatrixCSC) (rowind, colind) end -function bunchkaufman_instance(A::SparseMatrixCSC) - bunchkaufman(sparse(similar(A, 1, 1)), check = false) +function bunchkaufman_instance(A::SparseMatrixCSC{Tv, Ti}) where {Tv, Ti} + bunchkaufman(SparseMatrixCSC{Tv, Ti}(similar(A, 1, 1)), check = false) end -function cholesky_instance(A::Union{SparseMatrixCSC,Symmetric{<:Number,<:SparseMatrixCSC}}, pivot = DEFAULT_CHOLESKY_PIVOT) - cholesky(sparse(similar(A, 1, 1)), check = false) +function cholesky_instance(A::Union{SparseMatrixCSC{Tv, Ti},Symmetric{<:Number,<:SparseMatrixCSC{Tv, Ti}}}, pivot = DEFAULT_CHOLESKY_PIVOT) where {Tv, Ti} + cholesky(SparseMatrixCSC{Tv, Ti}(similar(A, 1, 1)), check = false) end -function ldlt_instance(A::SparseMatrixCSC) - ldlt(sparse(similar(A, 1, 1)), check=false) +function ldlt_instance(A::SparseMatrixCSC{Tv, Ti}) where {Tv, Ti} + ldlt(SparseMatrixCSC{Tv, Ti}(similar(A, 1, 1)), check=false) end # Could be optimized but this should work for any real case. -function lu_instance(jac_prototype::SparseMatrixCSC, pivot = DEFAULT_CHOLESKY_PIVOT) - lu(sparse(rand(1,1))) +function lu_instance(jac_prototype::SparseMatrixCSC{Tv, Ti}, pivot = DEFAULT_CHOLESKY_PIVOT) where {Tv, Ti} + lu(SparseMatrixCSC{Tv, Ti}(rand(1,1))) end -function qr_instance(jac_prototype::SparseMatrixCSC, pivot = DEFAULT_CHOLESKY_PIVOT) - qr(sparse(rand(1,1))) +function qr_instance(jac_prototype::SparseMatrixCSC{Tv, Ti}, pivot = DEFAULT_CHOLESKY_PIVOT) where {Tv, Ti} + qr(SparseMatrixCSC{Tv, Ti}(rand(1,1))) end end diff --git a/test/ad.jl b/test/ad.jl index bc3c3dd80..3c61873e6 100644 --- a/test/ad.jl +++ b/test/ad.jl @@ -1,6 +1,9 @@ using ArrayInterface, ReverseDiff, Tracker, Test x = ReverseDiff.track([4.0]) @test ArrayInterface.aos_to_soa(x) isa ReverseDiff.TrackedArray +x = reshape([ReverseDiff.track(rand(1, 1, 1))[1]], 1, 1, 1) +@test ArrayInterface.aos_to_soa(x) isa ReverseDiff.TrackedArray +@test ndims(ArrayInterface.aos_to_soa(x)) == 3 x = reduce(vcat, ReverseDiff.track([4.0,4.0])) @test ArrayInterface.aos_to_soa(x) isa ReverseDiff.TrackedArray x = [ReverseDiff.track([4.0])[1]] diff --git a/test/gpu/Project.toml b/test/gpu/Project.toml index 0853fd7bb..1ef4f1022 100644 --- a/test/gpu/Project.toml +++ b/test/gpu/Project.toml @@ -1,2 +1,4 @@ [deps] -CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" \ No newline at end of file +CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" +CUDSS = "45b445bb-4962-46a0-9369-b4df9d0f772e" +Metal = "dde4c033-4e86-420c-a63e-0dd931031962" diff --git a/test/gpu/cuda.jl b/test/gpu/cuda.jl index f57bdafa7..2651a6381 100644 --- a/test/gpu/cuda.jl +++ b/test/gpu/cuda.jl @@ -1,7 +1,20 @@ -using CUDA +using CUDSS, CUDA, SparseArrays, LinearAlgebra +using CUDA.CUSPARSE using ArrayInterface using Test +A_cpu = Float32[1 0; 0 1] +A_dense = CuMatrix(A_cpu) +A_sparse = CuSparseMatrixCSR(sparse(A_cpu)) + # Test whether lu_instance throws an error when invoked with an gpu array -@test !isa(try ArrayInterface.lu_instance(CUDA.CuArray([1.f0 1.f0; 1.f0 1.f0])) catch ex ex end, Exception) +lu_inst_dense = ArrayInterface.lu_instance(A_dense) +lu_inst_sparse = ArrayInterface.lu_instance(A_sparse) + +# test that lu! is valid when using the inst as scratch +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] diff --git a/test/gpu/metal.jl b/test/gpu/metal.jl new file mode 100644 index 000000000..c819a05ee --- /dev/null +++ b/test/gpu/metal.jl @@ -0,0 +1,8 @@ +using Metal +using ArrayInterface +using LinearAlgebra + +using Test + +# Test that lu_instance works with Metal.jl gpu arrays +@test isa(ArrayInterface.lu_instance(MtlArray([1.f0 1.f0; 1.f0 1.f0])), LU) \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index 8a5d7b363..cd47c19fb 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -21,5 +21,8 @@ end if GROUP == "GPU" activate_gpu_env() @time @safetestset "CUDA" begin include("gpu/cuda.jl") end + if Sys.isapple() + @time @safetestset "Metal" begin include("gpu/metal.jl") end + end end end