@@ -163,53 +163,62 @@ struct SVMBackend <: AbstractMemoryBackend end
163
163
struct USMBackend <: AbstractMemoryBackend end
164
164
struct BDABackend <: AbstractMemoryBackend end
165
165
166
- function default_memory_backend (dev:: Device )
167
- # determine if USM is supported
168
- usm = if usm_supported (dev)
169
- caps = usm_capabilities (dev)
170
- caps. host. access && caps. device. access
171
- else
172
- false
166
+ function supported_memory_backends (dev:: Device )
167
+ backends = AbstractMemoryBackend[]
168
+
169
+ # unified shared memory is the first choice, as it gives us separate host and device
170
+ # memory spaces that can be directly referenced by raw pointers.
171
+ if usm_supported (dev)
172
+ usm_caps = usm_capabilities (dev)
173
+ if usm_caps. host. access && usm_caps. device. access
174
+ push! (backends, USMBackend ())
175
+ end
173
176
end
174
177
175
- bda = bda_supported (dev)
178
+ # plain old device buffers are second choice, but require an extension to support being
179
+ # referenced by raw pointers.
180
+ if bda_supported (dev)
181
+ push! (backends, BDABackend ())
182
+ end
176
183
177
- # determine if SVM is available (if needed)
178
- svm = let
179
- caps = svm_capabilities (dev)
180
- caps . coarse_grain_buffer
184
+ # shared virtual memory is last, because it comes at a performance cost.
185
+ svm_caps = svm_capabilities (dev)
186
+ if svm_caps . coarse_grain_buffer
187
+ push! (backends, SVMBackend ())
181
188
end
182
189
190
+ return backends
191
+ end
192
+
193
+ function default_memory_backend (dev:: Device )
194
+ supported_backends = supported_memory_backends (dev)
195
+ isempty (supported_backends) && return nothing
196
+
183
197
preferred_backend = load_preference (OpenCL, " memory_backend" , " auto" )
184
198
if preferred_backend == " auto"
185
- if usm
199
+ first (supported_backends)
200
+ else
201
+ backend = if preferred_backend == " usm"
186
202
USMBackend ()
203
+ elseif preferred_backend == " bda"
204
+ BDABackend ()
205
+ elseif preferred_backend == " svm"
206
+ SVMBackend ()
187
207
else
188
- if svm
189
- SVMBackend ()
190
- elseif bda
191
- BDABackend ()
192
- else
193
- error (" Device $dev does not support USM, coarse-grained SVM, or Buffer Device Address, one of which is required by OpenCL.jl" )
194
- end
208
+ error (" Unknown memory backend '$preferred_backend ' requested" )
195
209
end
196
- elseif preferred_backend == " usm"
197
- usm || error (" Use of USM memory backend requested, which is not supported by device $dev " )
198
- USMBackend ()
199
- elseif preferred_backend == " bda"
200
- bda || error (" Use of Buffer Device Address memory backend requested, which is not supported by device $dev " )
201
- BDABackend ()
202
- elseif preferred_backend == " svm"
203
- svm || error (" Use of coarse-grained SVM memory backend requested, which is not supported by device $dev " )
204
- SVMBackend ()
205
- else
206
- error (" Unknown memory backend '$preferred_backend ' requested" )
210
+ in (backend, supported_backends) || return nothing
211
+ backend
207
212
end
208
213
end
209
214
210
215
function memory_backend ()
211
216
return get! (task_local_storage (), :CLMemoryBackend ) do
212
- default_memory_backend (device ())
217
+ backend = default_memory_backend (device ())
218
+ if backend === nothing
219
+ error (" Device $(device ()) does not support any of the available memory backends" )
220
+ end
221
+ backend
213
222
end
214
223
end
215
224
0 commit comments