Skip to content
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

RFC: Establish concept of a computing device #52

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
3 changes: 3 additions & 0 deletions src/Adapt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,7 @@ include("arrays.jl")
# helpers
include("macro.jl")

# compute devices
include("computedevs.jl")

end # module
80 changes: 80 additions & 0 deletions src/computedevs.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# adaptors for converting abstract arrays to Base.Array


"""
abstract type AbstractComputingDevice

Supertype for CPU and GPU computing devices.
oschulz marked this conversation as resolved.
Show resolved Hide resolved

`adapt(dev::AbstractComputingDevice, x)` adapts `x` for `dev`.
"""
abstract type AbstractComputingDevice end
export AbstractComputingDevice


"""
struct ComputingDeviceIndependent <: AbstractComputingDevice

`get_computing_device(x) === ComputingDeviceIndependent()` indicates
that `x` is not tied to a specific computing device. This typically
means that x is a statically allocated object.
"""
struct ComputingDeviceIndependent <: AbstractComputingDevice end
export ComputingDeviceIndependent


"""
struct CPUDevice <: AbstractComputingDevice

`CPUDevice()` is the default CPU device.
"""
struct CPUDevice <: AbstractComputingDevice end
export CPUDevice
oschulz marked this conversation as resolved.
Show resolved Hide resolved



"""
abstract type AbstractGPUDevice <: AbstractComputingDevice

Supertype for GPU computing devices.
"""
abstract type AbstractGPUDevice <: AbstractComputingDevice end
oschulz marked this conversation as resolved.
Show resolved Hide resolved
export AbstractGPUDevice



const _incompatible_devs = ArgumentError("Incompatible computing devices")

select_computing_device(a::ComputingDeviceIndependent, ::ComputingDeviceIndependent) = a
oschulz marked this conversation as resolved.
Show resolved Hide resolved
select_computing_device(a::ComputingDeviceIndependent, b::AbstractComputingDevice) = b
select_computing_device(a::AbstractComputingDevice, b::ComputingDeviceIndependent) = a

select_computing_device(a::CPUDevice, ::CPUDevice) = a
select_computing_device(a::CPUDevice, b::AbstractGPUDevice) = a
select_computing_device(a::AbstractGPUDevice, b::CPUDevice) = b
oschulz marked this conversation as resolved.
Show resolved Hide resolved
select_computing_device(a::AbstractGPUDevice, b::AbstractGPUDevice) = (a === b) ? a : throw(_incompatible_devs)
oschulz marked this conversation as resolved.
Show resolved Hide resolved


"""
get_computing_device(x)::AbstractComputingDevice

Get the computing device backing object `x`.
"""
function get_computing_device end
export get_computing_device


@inline get_computing_device(::Array) = CPUDevice()

# ToDo: Utilize `ArrayInterfaceCore.buffer(A)`? Would require Adapt to depend
# on ArrayInterfaceCore.

@generated function get_computing_device(x)
impl = :(begin dev_0 = ComputingDeviceIndependent() end)
append!(impl.args, [:($(Symbol(:dev_, i)) = select_computing_device(get_computing_device(getfield(x, $i)), $(Symbol(:dev_, i-1)))) for i in 1:fieldcount(x)])
push!(impl.args, :(return $(Symbol(:dev_, fieldcount(x)))))
impl
end
oschulz marked this conversation as resolved.
Show resolved Hide resolved


adapt_storage(::CPUDevice, x) = adapt_storage(Array, x)