Skip to content

Commit 89ad72f

Browse files
authored
[KA] support unified memory API (#394)
1 parent 11ed992 commit 89ad72f

File tree

3 files changed

+37
-12
lines changed

3 files changed

+37
-12
lines changed

Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "OpenCL"
22
uuid = "08131aa3-fb12-5dee-8b74-c09406e224a2"
3-
version = "0.10.7"
3+
version = "0.10.8"
44

55
[deps]
66
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
@@ -28,7 +28,7 @@ SPIRVIntrinsics = {path = "lib/intrinsics"}
2828
Adapt = "4"
2929
GPUArrays = "11.2.1"
3030
GPUCompiler = "1.7.1"
31-
KernelAbstractions = "0.9.2"
31+
KernelAbstractions = "0.9.38"
3232
LLVM = "9.1"
3333
LinearAlgebra = "1"
3434
OpenCL_jll = "=2024.10.24"

lib/cl/state.jl

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ function clear_task_local_storage!()
99
delete!(task_local_storage(), :CLPlatform)
1010
delete!(task_local_storage(), :CLQueue)
1111
delete!(task_local_storage(), :CLMemoryBackend)
12+
delete!(task_local_storage(), :CLUnifiedMemoryBackend)
1213
end
1314

1415

@@ -163,7 +164,7 @@ struct SVMBackend <: AbstractMemoryBackend end
163164
struct USMBackend <: AbstractMemoryBackend end
164165
struct BufferBackend <: AbstractMemoryBackend end
165166

166-
function supported_memory_backends(dev::Device)
167+
function supported_memory_backends(dev::Device; unified=false)
167168
backends = AbstractMemoryBackend[]
168169

169170
# unified shared memory is the first choice, as it gives us separate host and device
@@ -177,7 +178,7 @@ function supported_memory_backends(dev::Device)
177178

178179
# plain old buffers are always supported, but we only want to use them if we have the
179180
# buffer device address extension, which allows us to reference them by raw pointers.
180-
if bda_supported(dev)
181+
if !unified && bda_supported(dev)
181182
push!(backends, BufferBackend())
182183
end
183184

@@ -187,7 +188,7 @@ function supported_memory_backends(dev::Device)
187188
push!(backends, SVMBackend())
188189
end
189190

190-
if isempty(backends)
191+
if !unified && isempty(backends)
191192
# as a last resort, use plain buffers without the ability to reference by pointer.
192193
# this severely limits compatibility, but it's better than nothing.
193194
push!(backends, BufferBackend())
@@ -196,8 +197,9 @@ function supported_memory_backends(dev::Device)
196197
return backends
197198
end
198199

199-
function default_memory_backend(dev::Device)
200-
supported_backends = supported_memory_backends(dev)
200+
function default_memory_backend(dev::Device; unified=false)
201+
supported_backends = supported_memory_backends(dev; unified)
202+
isempty(supported_backends) && return nothing
201203

202204
backend_str = load_preference(OpenCL, "default_memory_backend")
203205
backend_str === nothing && return first(supported_backends)
@@ -211,8 +213,7 @@ function default_memory_backend(dev::Device)
211213
else
212214
error("Unknown memory backend '$backend_str' requested")
213215
end
214-
in(backend, supported_backends) ? backend : nothing
215-
backend
216+
return in(backend, supported_backends) ? backend : nothing
216217
end
217218

218219
function memory_backend()
@@ -230,6 +231,17 @@ function memory_backend()
230231
end
231232
end
232233

234+
function unified_memory_backend()
235+
return get!(task_local_storage(), :CLUnifiedMemoryBackend) do
236+
dev = device()
237+
backend = default_memory_backend(dev; unified=true)
238+
if backend === nothing
239+
error("Device $(dev) does not support any of the available unified memory backends")
240+
end
241+
backend
242+
end
243+
end
244+
233245

234246
## per-task queues
235247

src/OpenCLKernels.jl

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,22 @@ export OpenCLBackend
1717
struct OpenCLBackend <: KA.GPU
1818
end
1919

20-
KA.allocate(::OpenCLBackend, ::Type{T}, dims::Tuple) where T = CLArray{T}(undef, dims)
21-
KA.zeros(::OpenCLBackend, ::Type{T}, dims::Tuple) where T = OpenCL.zeros(T, dims)
22-
KA.ones(::OpenCLBackend, ::Type{T}, dims::Tuple) where T = OpenCL.ones(T, dims)
20+
function KA.allocate(::OpenCLBackend, ::Type{T}, dims::Tuple; unified::Bool = false) where T
21+
if unified
22+
memory_backend = cl.unified_memory_backend()
23+
if memory_backend === cl.USMBackend()
24+
return CLArray{T, length(dims), cl.UnifiedSharedMemory}(undef, dims)
25+
elseif memory_backend === cl.SVMBackend()
26+
return CLArray{T, length(dims), cl.SharedVirtualMemory}(undef, dims)
27+
else
28+
throw(ArgumentError("Unified memory not supported"))
29+
end
30+
else
31+
return CLArray{T}(undef, dims)
32+
end
33+
end
34+
35+
KA.supports_unified(::OpenCLBackend) = cl.default_memory_backend(cl.device(); unified=true) !== nothing
2336

2437
KA.get_backend(::CLArray) = OpenCLBackend()
2538
# TODO should be non-blocking

0 commit comments

Comments
 (0)