Skip to content

Commit 1a580ab

Browse files
Unified memory allocations (#632)
1 parent 434d55a commit 1a580ab

File tree

4 files changed

+54
-18
lines changed

4 files changed

+54
-18
lines changed

docs/src/api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ allocate
2121

2222
```@docs
2323
KernelAbstractions.zeros
24+
KernelAbstractions.supports_unified
2425
```
2526

2627
## Internal

src/KernelAbstractions.jl

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -532,40 +532,67 @@ get_backend(::Array) = CPU()
532532
Adapt.adapt_storage(::CPU, a::Array) = a
533533

534534
"""
535-
allocate(::Backend, Type, dims...)::AbstractArray
535+
allocate(::Backend, Type, dims...; unified=false)::AbstractArray
536536
537-
Allocate a storage array appropriate for the computational backend.
537+
Allocate a storage array appropriate for the computational backend. `unified=true`
538+
allocates an array using unified memory if the backend supports it and throws otherwise.
539+
Use [`supports_unified`](@ref) to determine whether it is supported by a backend.
538540
539541
!!! note
540542
Backend implementations **must** implement `allocate(::NewBackend, T, dims::Tuple)`
541-
"""
542-
allocate(backend::Backend, T::Type, dims...) = allocate(backend, T, dims)
543-
allocate(backend::Backend, T::Type, dims::Tuple) = throw(MethodError(allocate, (backend, T, dims)))
543+
Backend implementations **should** implement `allocate(::NewBackend, T, dims::Tuple; unified::Bool=false)`
544+
"""
545+
allocate(backend::Backend, T::Type, dims...; kwargs...) = allocate(backend, T, dims; kwargs...)
546+
function allocate(backend::Backend, T::Type, dims::Tuple; unified::Union{Nothing, Bool} = nothing)
547+
if isnothing(unified)
548+
throw(MethodError(allocate, (backend, T, dims)))
549+
elseif unified
550+
throw(ArgumentError("`$(typeof(backend))` does not support unified memory. If you believe it does, please open a github issue."))
551+
else
552+
return allocate(backend, T, dims)
553+
end
554+
end
555+
544556

545557
"""
546-
zeros(::Backend, Type, dims...)::AbstractArray
558+
zeros(::Backend, Type, dims...; unified=false)::AbstractArray
547559
548560
Allocate a storage array appropriate for the computational backend filled with zeros.
561+
`unified=true` allocates an array using unified memory if the backend supports it and
562+
throws otherwise.
549563
"""
550-
zeros(backend::Backend, T::Type, dims...) = zeros(backend, T, dims)
551-
function zeros(backend::Backend, ::Type{T}, dims::Tuple) where {T}
552-
data = allocate(backend, T, dims...)
564+
zeros(backend::Backend, T::Type, dims...; kwargs...) = zeros(backend, T, dims; kwargs...)
565+
function zeros(backend::Backend, ::Type{T}, dims::Tuple; kwargs...) where {T}
566+
data = allocate(backend, T, dims...; kwargs...)
553567
fill!(data, zero(T))
554568
return data
555569
end
556570

557571
"""
558-
ones(::Backend, Type, dims...)::AbstractArray
572+
ones(::Backend, Type, dims...; unified=false)::AbstractArray
559573
560574
Allocate a storage array appropriate for the computational backend filled with ones.
575+
`unified=true` allocates an array using unified memory if the backend supports it and
576+
throws otherwise.
561577
"""
562-
ones(backend::Backend, T::Type, dims...) = ones(backend, T, dims)
563-
function ones(backend::Backend, ::Type{T}, dims::Tuple) where {T}
564-
data = allocate(backend, T, dims)
578+
ones(backend::Backend, T::Type, dims...; kwargs...) = ones(backend, T, dims; kwargs...)
579+
function ones(backend::Backend, ::Type{T}, dims::Tuple; kwargs...) where {T}
580+
data = allocate(backend, T, dims; kwargs...)
565581
fill!(data, one(T))
566582
return data
567583
end
568584

585+
"""
586+
supports_unified(::Backend)::Bool
587+
588+
Returns whether unified memory arrays are supported by the backend.
589+
590+
!!! note
591+
Backend implementations **should** implement this function
592+
only if they **do** support unified memory.
593+
"""
594+
supports_unified(::Backend) = false
595+
569596
"""
570597
supports_atomics(::Backend)::Bool
571598

src/cpu.jl

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
unsafe_free!(::AbstractArray) = return
22
synchronize(::CPU) = nothing
33

4-
allocate(::CPU, ::Type{T}, dims::Tuple) where {T} = Array{T}(undef, dims)
4+
allocate(::CPU, ::Type{T}, dims::Tuple; unified::Bool = false) where {T} = Array{T}(undef, dims)
55

6-
function zeros(backend::CPU, ::Type{T}, dims::Tuple) where {T}
7-
arr = allocate(backend, T, dims)
6+
function zeros(backend::CPU, ::Type{T}, dims::Tuple; kwargs...) where {T}
7+
arr = allocate(backend, T, dims; kwargs...)
88
kernel = init_kernel(backend)
99
kernel(arr, zero, T, ndrange = length(arr))
1010
return arr
1111
end
12-
function ones(backend::CPU, ::Type{T}, dims::Tuple) where {T}
13-
arr = allocate(backend, T, dims)
12+
function ones(backend::CPU, ::Type{T}, dims::Tuple; kwargs...) where {T}
13+
arr = allocate(backend, T, dims; kwargs...)
1414
kernel = init_kernel(backend)
1515
kernel(arr, one, T; ndrange = length(arr))
1616
return arr
@@ -34,6 +34,7 @@ end
3434

3535
functional(::CPU) = true
3636
pagelock!(::CPU, x) = nothing
37+
supports_unified(::CPU) = true
3738

3839
function (obj::Kernel{CPU})(args...; ndrange = nothing, workgroupsize = nothing)
3940
ndrange, workgroupsize, iterspace, dynamic = launch_config(obj, ndrange, workgroupsize)

test/test.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ function unittest_testsuite(Backend, backend_str, backend_mod, BackendArrayT; sk
7878
backendT = typeof(backend).name.wrapper # To look through CUDABackend{true, false}
7979
@test backend isa backendT
8080

81+
unified = KernelAbstractions.supports_unified(backend)
82+
@test unified isa Bool
83+
U = allocate(backend, Float32, 5; unified)
84+
if unified
85+
@test U[3] isa Float32
86+
end
87+
8188
x = allocate(backend, Float32, 5)
8289
A = allocate(backend, Float32, 5, 5)
8390
@test @inferred(KernelAbstractions.get_backend(A)) isa backendT

0 commit comments

Comments
 (0)