Skip to content

Commit 638624f

Browse files
authored
[NDTensors] Reorganize some GPU functions (#1352)
1 parent 54f53de commit 638624f

36 files changed

+223
-98
lines changed
+10-14
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,24 @@
1-
## Here we need an NDTensorCuArrayAdaptor because the CuArrayAdaptor provided by CUDA
2-
## converts 64 bit numbers to 32 bit. We cannot write `adapt(CuVector, x)` because this
3-
## Will not allow us to properly utilize the buffer preference without changing the value of
4-
## default_buffertype. Also `adapt(CuVector{<:Any, <:Any, Buffertype})` fails to work properly
5-
struct NDTensorCuArrayAdaptor{B} end
1+
using NDTensors.TypeParameterAccessors: TypeParameterAccessors
2+
using NDTensors.GPUArraysCoreExtensions: storagemode
3+
using NDTensors.CUDAExtensions: CUDAExtensions, CuArrayAdaptor
4+
65
## TODO make this work for unified. This works but overwrites CUDA's adapt_storage. This fails for emptystorage...
7-
function cu(xs; unified::Bool=false)
6+
function CUDAExtensions.cu(xs; unified::Bool=false)
87
return fmap(
9-
x -> adapt(NDTensorCuArrayAdaptor{unified ? Mem.UnifiedBuffer : Mem.DeviceBuffer}(), x),
10-
xs,
8+
x -> adapt(CuArrayAdaptor{unified ? Mem.UnifiedBuffer : Mem.DeviceBuffer}(), x), xs
119
)
1210
end
1311

14-
buffertype(::NDTensorCuArrayAdaptor{B}) where {B} = B
15-
16-
function Adapt.adapt_storage(adaptor::NDTensorCuArrayAdaptor, xs::AbstractArray)
12+
function Adapt.adapt_storage(adaptor::CuArrayAdaptor, xs::AbstractArray)
1713
ElT = eltype(xs)
18-
BufT = buffertype(adaptor)
14+
BufT = storagemode(adaptor)
1915
N = ndims(xs)
2016
return isbits(xs) ? xs : adapt(CuArray{ElT,N,BufT}, xs)
2117
end
2218

2319
function NDTensors.adapt_storagetype(
24-
adaptor::NDTensorCuArrayAdaptor, xs::Type{EmptyStorage{ElT,StoreT}}
20+
adaptor::CuArrayAdaptor, xs::Type{EmptyStorage{ElT,StoreT}}
2521
) where {ElT,StoreT}
26-
BufT = buffertype(adaptor)
22+
BufT = storagemode(adaptor)
2723
return NDTensors.emptytype(NDTensors.adapt_storagetype(CuVector{ElT,BufT}, StoreT))
2824
end
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import NDTensors: cu, similartype
1+
import NDTensors: similartype
22
import NDTensors:
33
ContractionProperties, _contract!, GemmBackend, auto_select_backend, _gemm!, iscu
44
import NDTensors.SetParameters: nparameters, get_parameter, set_parameter, default_parameter

NDTensors/ext/NDTensorsCUDAExt/set_types.jl

+17
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,20 @@ default_parameter(::Type{<:CuArray}, ::Position{3}) = Mem.DeviceBuffer
3838
nparameters(::Type{<:CuArray}) = Val(3)
3939

4040
SetParameters.unspecify_parameters(::Type{<:CuArray}) = CuArray
41+
42+
using NDTensors.TypeParameterAccessors: TypeParameterAccessors
43+
using NDTensors.GPUArraysCoreExtensions: storagemode
44+
## TODO remove TypeParameterAccessors when SetParameters is removed
45+
function TypeParameterAccessors.position(::Type{<:CuArray}, ::typeof(eltype))
46+
return TypeParameterAccessors.Position(1)
47+
end
48+
function TypeParameterAccessors.position(::Type{<:CuArray}, ::typeof(Base.ndims))
49+
return TypeParameterAccessors.Position(2)
50+
end
51+
function TypeParameterAccessors.position(::Type{<:CuArray}, ::typeof(storagemode))
52+
return TypeParameterAccessors.Position(3)
53+
end
54+
55+
function TypeParameterAccessors.default_type_parameters(::Type{<:CuArray})
56+
return (Float64, 1, CUDA.Mem.DeviceBuffer)
57+
end

NDTensors/ext/NDTensorsMetalExt/adapt.jl

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
NDTensors.cpu(e::Exposed{<:MtlArray}) = adapt(Array, e)
1+
using NDTensors.MetalExtensions: MetalExtensions
2+
using NDTensors.GPUArraysCoreExtensions: GPUArraysCoreExtensions
23

3-
function mtl(xs; storage=DefaultStorageMode)
4+
GPUArraysCoreExtensions.cpu(e::Exposed{<:MtlArray}) = adapt(Array, e)
5+
6+
function MetalExtensions.mtl(xs; storage=DefaultStorageMode)
47
return adapt(set_storagemode(MtlArray, storage), xs)
58
end
69

710
# More general than the version in Metal.jl
11+
## TODO Rewrite this using a custom `MtlArrayAdaptor` which will be written in `MetalExtensions`.
812
function Adapt.adapt_storage(arraytype::Type{<:MtlArray}, xs::AbstractArray)
913
params = get_parameters(xs)
1014
arraytype_specified = specify_parameters(arraytype, params...)

NDTensors/ext/NDTensorsMetalExt/imports.jl

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import NDTensors: mtl
21
import NDTensors.SetParameters: nparameters, get_parameter, set_parameter, default_parameter
32

43
using NDTensors.Expose: Exposed, unexpose, expose

NDTensors/ext/NDTensorsMetalExt/set_types.jl

+18-2
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,25 @@ default_parameter(::Type{<:MtlArray}, ::Position{3}) = Metal.DefaultStorageMode
3939

4040
nparameters(::Type{<:MtlArray}) = Val(3)
4141

42+
using NDTensors.TypeParameterAccessors: TypeParameterAccessors
43+
using NDTensors.GPUArraysCoreExtensions: storagemode
4244
# Metal-specific type parameter setting
43-
function set_storagemode(arraytype::Type{<:MtlArray}, storagemode)
44-
return set_parameter(arraytype, Position(3), storagemode)
45+
function set_storagemode(arraytype::Type{<:MtlArray}, param)
46+
return TypeParameterAccessors.set_type_parameter(arraytype, storagemode, param)
4547
end
4648

4749
SetParameters.unspecify_parameters(::Type{<:MtlArray}) = MtlArray
50+
## TODO remove TypeParameterAccessors when SetParameters is removed
51+
function TypeParameterAccessors.position(::Type{<:MtlArray}, ::typeof(eltype))
52+
return TypeParameterAccessors.Position(1)
53+
end
54+
function TypeParameterAccessors.position(::Type{<:MtlArray}, ::typeof(Base.ndims))
55+
return TypeParameterAccessors.Position(2)
56+
end
57+
function TypeParameterAccessors.position(::Type{<:MtlArray}, ::typeof(storagemode))
58+
return TypeParameterAccessors.Position(3)
59+
end
60+
61+
function TypeParameterAccessors.default_type_parameters(::Type{<:MtlArray})
62+
return (Float32, 1, Metal.DefaultStorageMode)
63+
end

NDTensors/ext/examples/NDTensorCUDA.jl

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using NDTensors
2-
using CUDA: CUDA, CuVector, cu, reshape
2+
using NDTensors.CUDAExtensions: cu
3+
using CUDA: CUDA, CuVector, reshape
34
using ITensors:
45
Index, ITensor, randomMPO, randomMPS, inner, orthogonalize, qr, siteinds, svd
56
using Test: @test
@@ -8,7 +9,7 @@ using Zygote: gradient
89
function main()
910
# using ITensorGPU
1011
cpu = NDTensors.cpu
11-
gpu = NDTensors.cu
12+
gpu = cu
1213
# Here is an example of how to utilize NDTensors based tensors with CUDA datatypes
1314
i = Index(2)
1415
j = Index(5)

NDTensors/ext/examples/NDTensorMetal.jl

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
using Metal: MtlVector, mtl
1+
using Metal: MtlVector
22
using NDTensors
3+
using NDTensors.MetalExtensions: mtl
34

45
using ITensors: ITensor, Index, randomITensor
56
using Test: @test
67
using Zygote: gradient
78

89
function main()
910
cpu = NDTensors.cpu
10-
gpu = NDTensors.mtl
11+
gpu = mtl
1112
# Here is an example of how to utilize NDTensors based tensors with CUDA datatypes
1213
i = Index(20)
1314
j = Index(5)

NDTensors/src/NDTensors.jl

-52
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,4 @@
11
module NDTensors
2-
# TODO: List types, macros, and functions being used.
3-
using Adapt
4-
using Base.Threads
5-
using Compat
6-
using Dictionaries
7-
using Folds
8-
using GPUArraysCore
9-
using InlineStrings
10-
using Random
11-
using LinearAlgebra
12-
using StaticArrays
13-
using Functors
14-
using HDF5
15-
using SimpleTraits
16-
using SplitApplyCombine
17-
using Strided
18-
using TimerOutputs
19-
using TupleTools
20-
21-
for lib in [
22-
:AlgorithmSelection,
23-
:AllocateData,
24-
:BaseExtensions,
25-
:UnspecifiedTypes,
26-
:TypeParameterAccessors,
27-
:Expose,
28-
:SetParameters,
29-
:BroadcastMapConversion,
30-
:RankFactorization,
31-
:Sectors,
32-
:GradedAxes,
33-
:TensorAlgebra,
34-
:SparseArrayInterface,
35-
:SparseArrayDOKs,
36-
:DiagonalArrays,
37-
:BlockSparseArrays,
38-
:NamedDimsArrays,
39-
:SmallVectors,
40-
:SortedSets,
41-
:TagSets,
42-
:UnallocatedArrays,
43-
]
44-
include("lib/$(lib)/src/$(lib).jl")
45-
@eval using .$lib: $lib
46-
end
47-
48-
using Base: @propagate_inbounds, ReshapedArray, DimOrInd, OneTo
49-
50-
using Base.Cartesian: @nexprs
51-
52-
using Base.Threads: @spawn
53-
542
#####################################
553
# Imports and exports
564
#

NDTensors/src/adapt.jl

+5-7
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
1+
using .GPUArraysCoreExtensions: GPUArraysCoreExtensions
12
adapt_structure(to, x::TensorStorage) = setdata(x, adapt(to, data(x)))
23
adapt_structure(to, x::Tensor) = setstorage(x, adapt(to, storage(x)))
34

45
## use unwrap cpu here because Expose is included before NDTensors
5-
Expose.cpu(eltype::Type{<:Number}, x) = fmap(x -> adapt(Array{eltype}, x), x)
6-
Expose.cpu(x) = fmap(x -> adapt(Array, x), x)
7-
8-
# Implemented in `ITensorGPU` and NDTensorCUDA
9-
function cu end
10-
11-
function mtl end
6+
function GPUArraysCoreExtensions.cpu(eltype::Type{<:Number}, x)
7+
return fmap(x -> adapt(Array{eltype}, x), x)
8+
end
9+
GPUArraysCoreExtensions.cpu(x) = fmap(x -> adapt(Array, x), x)
1210

1311
adapt_structure(to::Type{<:Number}, x::TensorStorage) = setdata(x, convert.(to, data(x)))
1412

NDTensors/src/imports.jl

+58-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,64 @@
33
# similar to:
44
# https://github.com/JuliaGPU/KernelAbstractions.jl
55
# https://github.com/oschulz/HeterogeneousComputing.jl
6-
using .Expose: cpu
6+
7+
using Adapt
8+
using Base.Threads
9+
using Compat
10+
using Dictionaries
11+
using Folds
12+
using GPUArraysCore
13+
using InlineStrings
14+
using Random
15+
using LinearAlgebra
16+
using StaticArrays
17+
using Functors
18+
using HDF5
19+
using SimpleTraits
20+
using SplitApplyCombine
21+
using Strided
22+
using TimerOutputs
23+
using TupleTools
24+
25+
for lib in [
26+
:AlgorithmSelection,
27+
:AllocateData,
28+
:BaseExtensions,
29+
:UnspecifiedTypes,
30+
:TypeParameterAccessors,
31+
:GPUArraysCoreExtensions,
32+
:CUDAExtensions,
33+
:MetalExtensions,
34+
:Expose,
35+
:SetParameters,
36+
:BroadcastMapConversion,
37+
:RankFactorization,
38+
:Sectors,
39+
:GradedAxes,
40+
:TensorAlgebra,
41+
:SparseArrayInterface,
42+
:SparseArrayDOKs,
43+
:DiagonalArrays,
44+
:BlockSparseArrays,
45+
:NamedDimsArrays,
46+
:SmallVectors,
47+
:SortedSets,
48+
:TagSets,
49+
:UnallocatedArrays,
50+
]
51+
include("lib/$(lib)/src/$(lib).jl")
52+
@eval using .$lib: $lib
53+
end
54+
55+
using Base: @propagate_inbounds, ReshapedArray, DimOrInd, OneTo
56+
57+
using Base.Cartesian: @nexprs
58+
59+
using Base.Threads: @spawn
60+
61+
using .CUDAExtensions: cu
62+
using .MetalExtensions: mtl
63+
using .GPUArraysCoreExtensions: cpu
764

865
import Base:
966
# Types
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
style = "blue"
2+
indent = 2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module CUDAExtensions
2+
include("cuda.jl")
3+
4+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using NDTensors.TypeParameterAccessors: TypeParameterAccessors
2+
using NDTensors.GPUArraysCoreExtensions: storagemode
3+
# Implemented in `ITensorGPU` and NDTensorCUDA
4+
function cu end
5+
6+
## Here we need an NDTensorCuArrayAdaptor because the CuArrayAdaptor provided by CUDA
7+
## converts 64 bit numbers to 32 bit. We cannot write `adapt(CuVector, x)` because this
8+
## Will not allow us to properly utilize the buffer preference without changing the value of
9+
## default_buffertype. Also `adapt(CuVector{<:Any, <:Any, Buffertype})` fails to work properly
10+
struct CuArrayAdaptor{B} end
11+
12+
## TODO remove TypeParameterAccessors when SetParameters is removed
13+
function TypeParameterAccessors.position(::Type{<:CuArrayAdaptor}, ::typeof(storagemode))
14+
return TypeParameterAccessors.Position(1)
15+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
@eval module $(gensym())
2+
using Test: @testset, @test
3+
using NDTensors.CUDAExtensions: cu, CuArrayAdaptor
4+
using NDTensors.GPUArraysCoreExtensions: storagemode
5+
@testset "cu function exists" begin
6+
@test cu isa Function
7+
@test storagemode(CuArrayAdaptor{1}) == 1
8+
end
9+
end

NDTensors/src/lib/Expose/src/exposed.jl

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ expose(object) = Exposed{unwrap_array_type(object),typeof(object)}(object)
88

99
unexpose(E::Exposed) = E.object
1010

11+
## TODO remove TypeParameterAccessors when SetParameters is removed
1112
TypeParameterAccessors.parenttype(type::Type{<:Exposed}) = parameter(type, parenttype)
1213
function TypeParameterAccessors.position(::Type{<:Exposed}, ::typeof(parenttype))
1314
return TypeParameterAccessors.Position(1)

NDTensors/src/lib/Expose/src/functions/abstractarray.jl

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
using NDTensors.GPUArraysCoreExtensions: GPUArraysCoreExtensions, cpu
2+
13
parent(E::Exposed) = parent(unexpose(E))
24

35
transpose(E::Exposed) = transpose(unexpose(E))
46

57
adjoint(E::Exposed) = adjoint(unexpose(E))
68

7-
cpu(E::Exposed) = cpu(unexpose(E))
9+
GPUArraysCoreExtensions.cpu(E::Exposed) = cpu(unexpose(E))
810

911
getindex(E::Exposed) = unexpose(E)[]
1012

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
style = "blue"
2+
indent = 2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
name = "GPUArraysCoreExtensions"
2+
3+
[deps]
4+
GPUArraysCore = "46192b85-c4d5-4398-a991-12ede77f4527"
5+
6+
[compat]
7+
GPUArraysCore = "0.1"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module GPUArraysCoreExtensions
2+
include("gpuarrayscore.jl")
3+
4+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using NDTensors.TypeParameterAccessors: TypeParameterAccessors, type_parameter
2+
3+
function storagemode(object)
4+
return storagemode(typeof(object))
5+
end
6+
function storagemode(type::Type)
7+
return type_parameter(type, storagemode)
8+
end
9+
10+
function cpu end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@eval module $(gensym())
2+
using Test: @testset, @test
3+
using NDTensors.GPUArraysCoreExtensions: storagemode
4+
@testset "Test Base" begin
5+
@test storagemode isa Function
6+
end
7+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
style = "blue"
2+
indent = 2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module MetalExtensions
2+
include("metal.jl")
3+
4+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Implemented in `ITensorGPU` and NDTensorCUDA
2+
function mtl end

0 commit comments

Comments
 (0)