@@ -163,53 +163,62 @@ struct SVMBackend <: AbstractMemoryBackend end
163163struct USMBackend <: AbstractMemoryBackend end
164164struct BDABackend <: AbstractMemoryBackend end
165165
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
173176 end
174177
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
176183
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 ())
181188 end
182189
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+
183197 preferred_backend = load_preference (OpenCL, " memory_backend" , " auto" )
184198 if preferred_backend == " auto"
185- if usm
199+ first (supported_backends)
200+ else
201+ backend = if preferred_backend == " usm"
186202 USMBackend ()
203+ elseif preferred_backend == " bda"
204+ BDABackend ()
205+ elseif preferred_backend == " svm"
206+ SVMBackend ()
187207 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" )
195209 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
207212 end
208213end
209214
210215function memory_backend ()
211216 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
213222 end
214223end
215224
0 commit comments