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

Add API for device selection #395

Open
jkravs opened this issue May 10, 2023 · 2 comments
Open

Add API for device selection #395

jkravs opened this issue May 10, 2023 · 2 comments
Labels
enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed

Comments

@jkravs
Copy link

jkravs commented May 10, 2023

From a short conversation with @vchuravy I learned that there is currently no way of selecting between different GPUs by the same vendor on a single host using KernelAbstractions. It seems that KA.jl always defaults to the GPU with the lowest index.

CUDA.jl offers this feature already, see https://cuda.juliagpu.org/stable/usage/multigpu/, I'm not sure about AMDGPU.jl and oneAPI.jl. KA.jl should maybe offer some backend agnostic API for this.

@vchuravy vchuravy added enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed labels May 10, 2023
@luraess
Copy link

luraess commented May 10, 2023

I'm not sure about AMDGPU.jl

The closest to CUDA.device! you can get in AMDGPU is AMDGPU.device_id! (see JuliaGPU/AMDGPU.jl@b80dc31). Note that device indexing is 1-based in AMDGPU vs 0-based in CUDA.

I have no insights for oneAPI or Metal.

@stemann
Copy link

stemann commented May 14, 2023

Something like the following pseudocode?

abstract type BackendDevice end

DeviceType(::Type{<:Backend})::Type{<:BackendDevice} # trait

devices(::TBackend)::AbstractVector{TBackendDevice} where {TBackend <: Backend, TBackendDevice = DeviceType(TBackend)}

device(::TBackend)::TBackendDevice where {TBackend <: Backend, TBackendDevice = DeviceType(TBackend)}

device!(dev::{<:BackendDevice})::Nothing # Selects dev device

function device(f::Function, dev::TBackendDevice)
    current_device = device()
    device!(dev)
    try
        f()
    finally
        device!(current_device)
    end
end

with e.g. CUDAKernels defining:

struct CUDAKernelDevice <: BackendDevice
    cu_device::CuDevice
end

KernelAbstractions.DeviceType(::Type{CUDABackend}) = CUDAKernelDevice

KernelAbstractions.devices(::CUDABackend) = CUDAKernelDevice.(devices())

KernelAbstractions.device(::CUDABackend) = CUDAKernelDevice(device())

KernelAbstractions.device!(dev::CUDAKernelDevice) = device!(dev.cu_device)

... and equivalent for ROCKernels, oneAPIKernels, and MetalKernels - seems like it can be implemented for all four backends.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

4 participants