Skip to content

Commit

Permalink
Refactoring GPU extensions (#1365)
Browse files Browse the repository at this point in the history
  • Loading branch information
kmp5VT authored Apr 12, 2024
1 parent 7880207 commit 2a6afa5
Show file tree
Hide file tree
Showing 55 changed files with 284 additions and 374 deletions.
11 changes: 5 additions & 6 deletions .github/workflows/test_itensorgaussianmps_ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,12 @@ jobs:
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- name: Install Julia dependencies
shell: julia --project=monorepo {0}
- name: Install Julia dependencies and run tests
shell: julia --depwarn=yes {0}
run: |
using Pkg;
Pkg.develop(path=".");
Pkg.activate(temp=true)
Pkg.develop(path="./NDTensors");
Pkg.develop(path=".");
Pkg.develop(path="./ITensorGaussianMPS");
- name: Run the tests
run: >
julia --project=monorepo --depwarn=yes -e 'using Pkg; Pkg.test("ITensorGaussianMPS")'
Pkg.test("ITensorGaussianMPS");
13 changes: 5 additions & 8 deletions .github/workflows/test_itensormps_ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,15 @@ jobs:
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- name: Install Julia dependencies
shell: julia --project=monorepo {0}
- name: Install Julia dependencies and run tests
shell: julia {0}
run: |
using Pkg;
Pkg.develop(path=".");
Pkg.activate(temp=true);
Pkg.develop(path="./NDTensors");
- name: Run the tests
shell: julia --project=monorepo {0}
run: |
using Pkg;
Pkg.develop(path=".");
# https://github.com/JuliaLang/Pkg.jl/pull/1226
Pkg.test("ITensors"; coverage=true, test_args=["mps"])
Pkg.test("ITensors"; coverage=true, test_args=["mps"]);
- uses: julia-actions/julia-uploadcodecov@latest
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
12 changes: 4 additions & 8 deletions .github/workflows/test_itensors_base_ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,13 @@ jobs:
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- name: Install Julia dependencies
shell: julia --project=monorepo {0}
- name: Install Julia dependencies and run tests
shell: julia {0}
run: |
using Pkg;
Pkg.develop(path=".");
Pkg.activate(temp=true)
Pkg.develop(path="./NDTensors");
- name: Run the tests
shell: julia --project=monorepo {0}
run: |
using Pkg;
# https://github.com/JuliaLang/Pkg.jl/pull/1226
Pkg.develop(path=".");
Pkg.test("ITensors"; coverage=true, test_args=["base"])
- uses: julia-actions/julia-uploadcodecov@latest
env:
Expand Down
11 changes: 5 additions & 6 deletions .github/workflows/test_itensorunicodeplots_ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,13 @@ jobs:
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- name: Install Julia dependencies
shell: julia --project=monorepo {0}
- name: Install Julia dependencies and run tests
shell: julia --depwarn=yes {0}
run: |
using Pkg;
Pkg.develop(path=".");
Pkg.activate(temp=true);
Pkg.develop(path="./NDTensors");
Pkg.develop(path=".");
Pkg.develop(path="./ITensorVisualizationBase");
Pkg.develop(path="./ITensorUnicodePlots");
- name: Run the tests
run: >
julia --project=monorepo --depwarn=yes -e 'using Pkg; Pkg.test("ITensorUnicodePlots")'
Pkg.test("ITensorUnicodePlots")
11 changes: 5 additions & 6 deletions .github/workflows/test_itensorvisualization_ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,12 @@ jobs:
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- name: Install Julia dependencies
shell: julia --project=monorepo {0}
- name: Install Julia dependencies and run tests
shell: julia --depwarn=yes {0}
run: |
using Pkg;
Pkg.develop(path=".");
Pkg.activate(temp=true);
Pkg.develop(path="./NDTensors");
Pkg.develop(path=".");
Pkg.develop(path="./ITensorVisualizationBase");
- name: Run the tests
run: |
julia --project=monorepo --depwarn=yes -e 'using Pkg; Pkg.test("ITensorVisualizationBase")'
Pkg.test("ITensorVisualizationBase")
11 changes: 5 additions & 6 deletions .github/workflows/test_ndtensors.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,11 @@ jobs:
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- name: Install Julia dependencies
shell: julia --project=monorepo {0}
- name: Install Julia dependencies and run tests
shell: julia --depwarn=yes {0}
run: |
using Pkg;
Pkg.develop(path=".");
Pkg.activate(temp=true);
Pkg.develop(path="./NDTensors");
- name: Run the tests
run: |
julia --project=monorepo --depwarn=yes -e 'using Pkg; Pkg.test("NDTensors")'
Pkg.develop(path=".");
Pkg.test("NDTensors");
2 changes: 1 addition & 1 deletion NDTensors/Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "NDTensors"
uuid = "23ae76d9-e61a-49c4-8f12-3f1a16adf9cf"
authors = ["Matthew Fishman <[email protected]>"]
version = "0.2.30"
version = "0.3.0"

[deps]
Accessors = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697"
Expand Down
1 change: 1 addition & 0 deletions NDTensors/ext/NDTensorsAMDGPUExt/NDTensorsAMDGPUExt.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module NDTensorsAMDGPUExt

include("append.jl")
include("copyto.jl")
include("set_types.jl")
include("adapt.jl")
Expand Down
2 changes: 1 addition & 1 deletion NDTensors/ext/NDTensorsAMDGPUExt/adapt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function Adapt.adapt_storage(adaptor::ROCArrayAdaptor, xs::AbstractArray)
end

function NDTensors.adapt_storagetype(
adaptor::ROCArrayAdaptor, xs::Type{EmptyStorage{ElT,StoreT}}
adaptor::ROCArrayAdaptor, ::Type{EmptyStorage{ElT,StoreT}}
) where {ElT,StoreT}
roctype = set_type_parameters(
ROCVector, (eltype, storagemode), (ElT, storagemode(adaptor))
Expand Down
8 changes: 8 additions & 0 deletions NDTensors/ext/NDTensorsAMDGPUExt/append.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using GPUArraysCore: @allowscalar
using AMDGPU: ROCArray
using NDTensors.Expose: Exposed, unexpose

## Warning this append function uses scalar indexing and is therefore extremely slow
function Base.append!(Ecollection::Exposed{<:ROCArray}, collections...)
return @allowscalar append!(unexpose(Ecollection), collections...)
end
12 changes: 1 addition & 11 deletions NDTensors/ext/NDTensorsCUDAExt/NDTensorsCUDAExt.jl
Original file line number Diff line number Diff line change
@@ -1,15 +1,5 @@
module NDTensorsCUDAExt

using NDTensors
using NDTensors.Expose
using Adapt
using Functors
using LinearAlgebra: LinearAlgebra, Adjoint, Transpose, mul!, svd
using CUDA
using CUDA.CUBLAS
using CUDA.CUSOLVER

include("imports.jl")
include("append.jl")
include("default_kwargs.jl")
include("copyto.jl")
include("set_types.jl")
Expand Down
30 changes: 16 additions & 14 deletions NDTensors/ext/NDTensorsCUDAExt/adapt.jl
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
using NDTensors.TypeParameterAccessors: TypeParameterAccessors
using NDTensors.GPUArraysCoreExtensions: storagemode
using Adapt: Adapt
using CUDA: CUDA, CuArray, CuVector
using Functors: fmap
using NDTensors: NDTensors, EmptyStorage, adapt_storagetype, emptytype
using NDTensors.CUDAExtensions: CUDAExtensions, CuArrayAdaptor
using NDTensors.GPUArraysCoreExtensions: storagemode
using NDTensors.TypeParameterAccessors:
default_type_parameter, set_type_parameters, type_parameters

## TODO make this work for unified. This works but overwrites CUDA's adapt_storage. This fails for emptystorage...
function CUDAExtensions.cu(xs; unified::Bool=false)
return fmap(
x -> adapt(CuArrayAdaptor{unified ? Mem.UnifiedBuffer : Mem.DeviceBuffer}(), x), xs
)
function CUDAExtensions.cu(xs; storagemode=default_type_parameter(CuArray, storagemode))
return fmap(x -> adapt(CuArrayAdaptor{storagemode}(), x), xs)
end

## Could do this generically
function Adapt.adapt_storage(adaptor::CuArrayAdaptor, xs::AbstractArray)
ElT = eltype(xs)
BufT = storagemode(adaptor)
N = ndims(xs)
return isbits(xs) ? xs : adapt(CuArray{ElT,N,BufT}, xs)
params = (type_parameters(xs, (eltype, ndims))..., storagemode(adaptor))
cutype = set_type_parameters(CuArray, (eltype, ndims, storagemode), params)
return isbits(xs) ? xs : adapt(cutype, xs)
end

function NDTensors.adapt_storagetype(
adaptor::CuArrayAdaptor, xs::Type{EmptyStorage{ElT,StoreT}}
adaptor::CuArrayAdaptor, ::Type{EmptyStorage{ElT,StoreT}}
) where {ElT,StoreT}
BufT = storagemode(adaptor)
return NDTensors.emptytype(NDTensors.adapt_storagetype(CuVector{ElT,BufT}, StoreT))
cutype = set_type_parameters(CuVector, (eltype, storagemode), (ElT, storagemode(adaptor)))
return emptytype(adapt_storagetype(cutype, StoreT))
end
8 changes: 8 additions & 0 deletions NDTensors/ext/NDTensorsCUDAExt/append.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using GPUArraysCore: @allowscalar
using CUDA: CuArray
using NDTensors.Expose: Exposed, unexpose

## Warning this append function uses scalar indexing and is therefore extremely slow
function Base.append!(Ecollection::Exposed{<:CuArray}, collections...)
return @allowscalar append!(unexpose(Ecollection), collections...)
end
4 changes: 4 additions & 0 deletions NDTensors/ext/NDTensorsCUDAExt/copyto.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
using CUDA: CuArray
using NDTensors.Expose: Exposed, expose, unexpose
using LinearAlgebra: Adjoint

# Same definition as `MtlArray`.
function Base.copy(src::Exposed{<:CuArray,<:Base.ReshapedArray})
return reshape(copy(parent(src)), size(unexpose(src)))
Expand Down
3 changes: 3 additions & 0 deletions NDTensors/ext/NDTensorsCUDAExt/default_kwargs.jl
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
using CUDA: CuArray
using NDTensors: NDTensors

NDTensors.default_svd_alg(::Type{<:CuArray}, a) = "qr_algorithm"
3 changes: 0 additions & 3 deletions NDTensors/ext/NDTensorsCUDAExt/imports.jl

This file was deleted.

9 changes: 7 additions & 2 deletions NDTensors/ext/NDTensorsCUDAExt/indexing.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
using CUDA: CuArray
using GPUArraysCore: @allowscalar
using NDTensors: NDTensors
using NDTensors.Expose: Exposed, expose, unexpose

function Base.getindex(E::Exposed{<:CuArray})
return CUDA.@allowscalar unexpose(E)[]
return @allowscalar unexpose(E)[]
end

function Base.setindex!(E::Exposed{<:CuArray}, x::Number)
CUDA.@allowscalar unexpose(E)[] = x
@allowscalar unexpose(E)[] = x
return unexpose(E)
end

Expand Down
5 changes: 4 additions & 1 deletion NDTensors/ext/NDTensorsCUDAExt/iscu.jl
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
iscu(::Type{<:CuArray}) = true
using CUDA: CuArray
using NDTensors: NDTensors

NDTensors.iscu(::Type{<:CuArray}) = true
10 changes: 7 additions & 3 deletions NDTensors/ext/NDTensorsCUDAExt/linearalgebra.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
using Adapt: adapt
using CUDA: CUDA, CuMatrix
using LinearAlgebra: Adjoint, svd
using NDTensors: NDTensors
using NDTensors.Expose: Expose, expose, ql, ql_positive
using NDTensors.GPUArraysCoreExtensions: cpu
using NDTensors.TypeParameterAccessors: unwrap_array_type
function NDTensors.svd_catch_error(A::CuMatrix; alg::String="jacobi_algorithm")
if alg == "jacobi_algorithm"
alg = CUDA.CUSOLVER.JacobiAlgorithm()
Expand Down Expand Up @@ -42,9 +49,6 @@ function NDTensors.svd_catch_error(A::CuMatrix, ::CUDA.CUSOLVER.QRAlgorithm)
return USV
end

using NDTensors.GPUArraysCoreExtensions: cpu
using NDTensors.Expose: Expose, expose, ql, ql_positive
using NDTensors.TypeParameterAccessors: unwrap_array_type
## TODO currently AMDGPU doesn't have ql so make a ql function
function Expose.ql(A::Exposed{<:CuMatrix})
Q, L = ql(expose(cpu(A)))
Expand Down
4 changes: 4 additions & 0 deletions NDTensors/ext/NDTensorsCUDAExt/mul.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
using CUDA: CuArray
using LinearAlgebra: LinearAlgebra, mul!, transpose
using NDTensors.Expose: Exposed, expose, unexpose

# This was calling generic matrix multiplication.
# TODO: Raise an issue with `CUDA.jl`.
function LinearAlgebra.mul!(
Expand Down
3 changes: 3 additions & 0 deletions NDTensors/ext/NDTensorsCUDAExt/permutedims.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
using CUDA: CuArray
using NDTensors.Expose: Exposed, expose, unexpose

function Base.permutedims!(
Edest::Exposed{<:CuArray,<:Base.ReshapedArray}, Esrc::Exposed{<:CuArray}, perm
)
Expand Down
1 change: 1 addition & 0 deletions NDTensors/ext/NDTensorsCUDAExt/set_types.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# TypeParameterAccessors definitions
using CUDA: CUDA, CuArray
using NDTensors.TypeParameterAccessors: TypeParameterAccessors, Position
using NDTensors.GPUArraysCoreExtensions: storagemode

Expand Down
9 changes: 0 additions & 9 deletions NDTensors/ext/NDTensorsMetalExt/NDTensorsMetalExt.jl
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
module NDTensorsMetalExt

using Adapt
using Functors
using LinearAlgebra: LinearAlgebra, Adjoint, Transpose, mul!, qr, eigen, svd
using NDTensors
using NDTensors.Expose: qr_positive, ql_positive, ql

using Metal

include("imports.jl")
include("adapt.jl")
include("set_types.jl")
include("indexing.jl")
Expand Down
34 changes: 23 additions & 11 deletions NDTensors/ext/NDTensorsMetalExt/adapt.jl
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
using NDTensors.MetalExtensions: MetalExtensions
using NDTensors.GPUArraysCoreExtensions: GPUArraysCoreExtensions, set_storagemode
using NDTensors.TypeParameterAccessors: specify_type_parameters, type_parameters
using Adapt: Adapt, adapt
using Functors: fmap
using Metal: MtlArray, MtlVector, DefaultStorageMode
using NDTensors: NDTensors, EmptyStorage, adapt_storagetype, emptytype
using NDTensors.Expose: Exposed
using NDTensors.MetalExtensions: MetalExtensions, MtlArrayAdaptor
using NDTensors.GPUArraysCoreExtensions: GPUArraysCoreExtensions
using NDTensors.TypeParameterAccessors: set_type_parameters, type_parameters

GPUArraysCoreExtensions.cpu(e::Exposed{<:MtlArray}) = adapt(Array, e)

function MetalExtensions.mtl(xs; storage=DefaultStorageMode)
return adapt(set_storagemode(MtlArray, storage), xs)
function MetalExtensions.mtl(xs; storagemode=DefaultStorageMode)
return fmap(x -> adapt(MtlArrayAdaptor{storagemode}(), x), xs)
end

# More general than the version in Metal.jl
## TODO Rewrite this using a custom `MtlArrayAdaptor` which will be written in `MetalExtensions`.
function Adapt.adapt_storage(arraytype::Type{<:MtlArray}, xs::AbstractArray)
params = type_parameters(xs)
arraytype_specified = specify_type_parameters(arraytype, params)
return isbitstype(typeof(xs)) ? xs : convert(arraytype_specified, xs)
function Adapt.adapt_storage(adaptor::MtlArrayAdaptor, xs::AbstractArray)
new_parameters = (type_parameters(xs, (eltype, ndims))..., storagemode(adaptor))
mtltype = set_type_parameters(MtlArray, (eltype, ndims, storagemode), new_parameters)
return isbits(xs) ? xs : adapt(mtltype, xs)
end

function NDTensors.adapt_storagetype(
adaptor::MtlArrayAdaptor, ::Type{EmptyStorage{ElT,StoreT}}
) where {ElT,StoreT}
mtltype = set_type_parameters(
MtlVector, (eltype, storagemode), (ElT, storagemode(adaptor))
)
return emptytype(adapt_storagetype(mtltype, StoreT))
end
13 changes: 9 additions & 4 deletions NDTensors/ext/NDTensorsMetalExt/append.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# This circumvents an issues that `MtlArray` can't call `resize!`.
# TODO: Raise an issue with Metal.jl.
function NDTensors.append!!(::Type{<:MtlArray}, collection, collections...)
return vcat(collection, collections...)
## Right now append! is broken on metal because of a missing resize! function
## but make this available in the next release this will allow metal to work working
using GPUArraysCore: @allowscalar
using Metal: MtlArray
using NDTensors.Expose: Exposed, unexpose

## Warning this append function uses scalar indexing and is therefore extremely slow
function Base.append!(Ecollection::Exposed{<:MtlArray}, collections...)
return @allowscalar append!(unexpose(Ecollection), collections...)
end
3 changes: 3 additions & 0 deletions NDTensors/ext/NDTensorsMetalExt/copyto.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
using Metal: MtlArray
using NDTensors.Expose: Exposed, expose, unexpose

function Base.copy(src::Exposed{<:MtlArray,<:Base.ReshapedArray})
return reshape(copy(parent(src)), size(unexpose(src)))
end
Expand Down
3 changes: 0 additions & 3 deletions NDTensors/ext/NDTensorsMetalExt/imports.jl

This file was deleted.

Loading

4 comments on commit 2a6afa5

@mtfishman
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator register subdir=NDTensors

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/104820

Tip: Release Notes

Did you know you can add release notes too? Just add markdown formatted text underneath the comment after the text
"Release notes:" and it will be added to the registry PR, and if TagBot is installed it will also be added to the
release that TagBot creates. i.e.

@JuliaRegistrator register

Release notes:

## Breaking changes

- blah

To add them here just re-invoke and the PR will be updated.

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a NDTensors-v0.3.0 -m "<description of version>" 2a6afa575531b679d185d2fc6a9ebde3e30f53db
git push origin NDTensors-v0.3.0

@mtfishman
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/104822

Tip: Release Notes

Did you know you can add release notes too? Just add markdown formatted text underneath the comment after the text
"Release notes:" and it will be added to the registry PR, and if TagBot is installed it will also be added to the
release that TagBot creates. i.e.

@JuliaRegistrator register

Release notes:

## Breaking changes

- blah

To add them here just re-invoke and the PR will be updated.

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.3.67 -m "<description of version>" 2a6afa575531b679d185d2fc6a9ebde3e30f53db
git push origin v0.3.67

Please sign in to comment.