Skip to content

Unified memory allocations #630

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/src/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ allocate

```@docs
KernelAbstractions.zeros
KernelAbstractions.supports_unified
```

## Internal
Expand Down
57 changes: 42 additions & 15 deletions src/KernelAbstractions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -524,47 +524,74 @@ end
# adapt_storage(::Backend, a::BackendArray) = a

"""
allocate(::Backend, Type, dims...)::AbstractArray
allocate(::Backend, Type, dims...; unified=false)::AbstractArray

Allocate a storage array appropriate for the computational backend.
Allocate a storage array appropriate for the computational backend. `unified=true`
allocates an array using unified memory if the backend supports it and throws otherwise.
Use [`supports_unified`](@ref) to determine whether it is supported by a backend.

!!! note
Backend implementations **must** implement `allocate(::NewBackend, T, dims::Tuple)`
"""
allocate(backend::Backend, T::Type, dims...) = allocate(backend, T, dims)
allocate(backend::Backend, T::Type, dims::Tuple) = throw(MethodError(allocate, (backend, T, dims)))
Backend implementations **should** implement `allocate(::NewBackend, T, dims::Tuple; unified::Bool=false)`
"""
allocate(backend::Backend, T::Type, dims...; kwargs...) = allocate(backend, T, dims; kwargs...)
function allocate(backend::Backend, T::Type, dims::Tuple; unified::Union{Nothing, Bool} = nothing)
if isnothing(unified)
throw(MethodError(allocate, (backend, T, dims)))
elseif unified
throw(ArgumentError("`$(typeof(backend))` does not support unified memory. If you believe it does, please open a github issue."))
else
return allocate(backend, T, dims)
end
end


"""
zeros(::Backend, Type, dims...)::AbstractArray
zeros(::Backend, Type, dims...; unified=false)::AbstractArray

Allocate a storage array appropriate for the computational backend filled with zeros.
`unified=true` allocates an array using unified memory if the backend supports it and
throws otherwise.
"""
zeros(backend::Backend, T::Type, dims...) = zeros(backend, T, dims)
function zeros(backend::Backend, ::Type{T}, dims::Tuple) where {T}
data = allocate(backend, T, dims...)
zeros(backend::Backend, T::Type, dims...; kwargs...) = zeros(backend, T, dims; kwargs...)
function zeros(backend::Backend, ::Type{T}, dims::Tuple; kwargs...) where {T}
data = allocate(backend, T, dims...; kwargs...)
fill!(data, zero(T))
return data
end

"""
ones(::Backend, Type, dims...)::AbstractArray
ones(::Backend, Type, dims...; unified=false)::AbstractArray

Allocate a storage array appropriate for the computational backend filled with ones.
`unified=true` allocates an array using unified memory if the backend supports it and
throws otherwise.
"""
ones(backend::Backend, T::Type, dims...) = ones(backend, T, dims)
function ones(backend::Backend, ::Type{T}, dims::Tuple) where {T}
data = allocate(backend, T, dims)
ones(backend::Backend, T::Type, dims...; kwargs...) = ones(backend, T, dims; kwargs...)
function ones(backend::Backend, ::Type{T}, dims::Tuple; kwargs...) where {T}
data = allocate(backend, T, dims; kwargs...)
fill!(data, one(T))
return data
end

"""
supports_unified(::Backend)::Bool

Returns whether unified memory arrays are supported by the backend.

!!! note
Backend implementations **must** implement this function
Copy link
Member Author

Choose a reason for hiding this comment

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

@vchuravy Yes ready to merge. Only thing I want to make sure you didn't miss is that contrary to the 0.9 PR, this has supports_unified as "must". I you would rather it still say "should" commit the suggestion. Either way merge away!

Suggested change
Backend implementations **must** implement this function
Backend implementations **should** implement this function

only if they **do** support unified memory.
"""
supports_unified(::Backend) = false

"""
supports_atomics(::Backend)::Bool

Returns whether `@atomic` operations are supported by the backend.

!!! note
Backend implementations **must** implement this function,
Backend implementations **must** implement this function
only if they **do not** support atomic operations with Atomix.
"""
supports_atomics(::Backend) = true
Expand All @@ -575,7 +602,7 @@ supports_atomics(::Backend) = true
Returns whether `Float64` values are supported by the backend.

!!! note
Backend implementations **must** implement this function,
Backend implementations **must** implement this function
only if they **do not** support `Float64`.
"""
supports_float64(::Backend) = true
Expand Down
224 changes: 0 additions & 224 deletions src/cpu.jl

This file was deleted.

11 changes: 6 additions & 5 deletions src/pocl/backend.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,16 @@ end

## Memory Operations

KA.allocate(::POCLBackend, ::Type{T}, dims::Tuple) where {T} = Array{T}(undef, dims)
KA.allocate(::POCLBackend, ::Type{T}, dims::Tuple; unified::Bool = false) where {T} = Array{T}(undef, dims)

function KA.zeros(backend::POCLBackend, ::Type{T}, dims::Tuple) where {T}
arr = KA.allocate(backend, T, dims)
function KA.zeros(backend::POCLBackend, ::Type{T}, dims::Tuple; kwargs...) where {T}
arr = KA.allocate(backend, T, dims; kwargs...)
kernel = KA.init_kernel(backend)
kernel(arr, zero, T, ndrange = length(arr))
return arr
end
function KA.ones(backend::POCLBackend, ::Type{T}, dims::Tuple) where {T}
arr = KA.allocate(backend, T, dims)
function KA.ones(backend::POCLBackend, ::Type{T}, dims::Tuple; kwargs...) where {T}
arr = KA.allocate(backend, T, dims; kwargs...)
kernel = KA.init_kernel(backend)
kernel(arr, one, T; ndrange = length(arr))
return arr
Expand Down Expand Up @@ -58,6 +58,7 @@ KA.pagelock!(::POCLBackend, x) = nothing
KA.get_backend(::Array) = POCLBackend()
KA.synchronize(::POCLBackend) = nothing
KA.supports_float64(::POCLBackend) = true
KA.supports_unified(::POCLBackend) = true


## Kernel Launch
Expand Down
9 changes: 9 additions & 0 deletions test/test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ function unittest_testsuite(Backend, backend_str, backend_mod, BackendArrayT; sk
backendT = typeof(backend).name.wrapper # To look through CUDABackend{true, false}
@test backend isa backendT

unified = KernelAbstractions.supports_unified(backend)
@test unified isa Bool
U = allocate(backend, Float32, 5; unified)
if unified
@test U[3] isa Float32
else
@test_throws ErrorException U[3]
end

x = allocate(backend, Float32, 5)
A = allocate(backend, Float32, 5, 5)
@test @inferred(KernelAbstractions.get_backend(A)) isa backendT
Expand Down
Loading