1
1
global current_context, make_current
2
+
2
3
function default_backend ()
3
4
if is_backend_supported (:cudanative )
4
5
CUBackend
@@ -9,22 +10,7 @@ function default_backend()
9
10
end
10
11
end
11
12
12
- let compute_contexts = Context[]
13
- function current_context ()
14
- if isempty (compute_contexts)
15
- default_backend (). init ()
16
- end
17
- last (compute_contexts)
18
- end
19
- all_contexts () = copy (compute_contexts)
20
- function make_current (ctx)
21
- idx = findfirst (compute_contexts, ctx)
22
- if idx != 0
23
- splice! (compute_contexts, idx) # remove
24
- end
25
- push! (compute_contexts, ctx)
26
- end
27
- end
13
+
28
14
# interface
29
15
function create_buffer (ctx, array) end
30
16
"""
@@ -34,38 +20,61 @@ function synchronize(A::AbstractArray)
34
20
# fallback is a noop, for backends not needing synchronization. This
35
21
# makes it easier to write generic code that also works for AbstractArrays
36
22
end
23
+
37
24
"""
38
25
`A` must be a gpu Array and will help to dispatch to the correct GPU backend
39
26
and can supply queues and contexts.
40
27
Calls `f` on args on the GPU, falls back to a normal call if there is no backend.
41
28
"""
42
- function gpu_call (A:: AbstractArray , f, args, worksize, localsize = nothing )
29
+ function gpu_call (f, A:: AbstractArray , args:: Tuple , worksize = length (A) , localsize = nothing )
43
30
f (args... )
44
31
end
45
32
46
- function free (x:: AbstractArray )
33
+ free (x:: AbstractArray ) = nothing
47
34
48
- end
49
35
#=
50
36
Functions to select contexts
51
37
=#
52
38
53
- is_gpu (ctx) = false
54
- is_cpu (ctx) = false
55
- is_opencl (ctx) = false
56
- is_cudanative (ctx) = false
57
- is_julia (ctx) = false
58
- is_opengl (ctx) = false
59
- has_atleast (ctx, attribute, value) = error (" has_atleast not implemented yet" )
39
+ threads (device) = 0
40
+ blocks (device) = 0
41
+ global_memory (device) = 0
42
+ free_global_memory (device) = NaN
43
+ local_memory (device) = 0
44
+ name (device) = " Undefined"
45
+
46
+ function device_summary (io:: IO , device)
47
+ println (io, " Device: " , name (device))
48
+ for (n, f) in (:threads => threads, :blocks => blocks)
49
+ @printf (io, " %19s: %s\n " , string (n), string (f (device)))
50
+ end
51
+ for (n, f) in (:global_memory => global_memory, :free_global_memory => free_global_memory, :local_memory => local_memory)
52
+ @printf (io, " %19s: %f mb\n " , string (n), f (device) / 10 ^ 6 )
53
+ end
54
+ return
55
+ end
56
+
57
+ # ###############################
58
+ # Device selection functions for e.g. devices(filterfuncs)
59
+ is_gpu (device) = false
60
+ is_cpu (device) = false
61
+ has_atleast (device, attribute, value) = attribute (ctx_or_device) >= value
62
+
63
+ """
64
+ Creates a new context from `device` without caching the resulting context.
65
+ """
66
+ function new_context (device)
67
+ error (" Device $device not supported" )
68
+ end
60
69
61
70
# BLAS support
62
71
hasblas (x) = false
63
72
include (" blas.jl" )
64
73
include (" supported_backends.jl" )
65
74
include (" shared.jl" )
66
75
67
- function to_backend_module (backend :: Symbol )
68
- if backend in supported_backends ()
76
+ function backend_module (sym :: Symbol )
77
+ if sym in supported_backends ()
69
78
if sym == :julia
70
79
JLBackend
71
80
elseif sym == :cudanative
82
91
function init (sym:: Symbol , args... ; kw_args... )
83
92
backend_module (sym). init (args... ; kw_args... )
84
93
end
94
+
85
95
function init (filterfuncs:: Function... ; kw_args... )
86
- init_from_device (first (devices (filterfuncs... )))
96
+ devices = available_devices (filterfuncs... )
97
+ if isempty (devices)
98
+ error (" No device found for: $(join (string .(filterfuncs), " " )) " )
99
+ end
100
+ current_backend (). init (first (devices))
101
+ end
102
+
103
+ active_backends () = backend_module .(supported_backends ())
104
+
105
+ const global_current_backend = Ref {Module} (default_backend ())
106
+
107
+ current_backend () = global_current_backend[]
108
+ current_device () = current_backend (). current_device ()
109
+ current_context () = current_backend (). current_context ()
110
+
111
+ """
112
+ Sets the current backend to be used globally. Accepts the symbols:
113
+ :cudanative, :opencl, :julia.
114
+ """
115
+ function setbackend! (backend:: Symbol )
116
+ setbackend! (backend_module (backend))
87
117
end
88
- backend_modules () = to_backend_module .(supported_backends ())
89
118
119
+ function setbackend! (backend:: Module )
120
+ global_current_backend[] = backend
121
+ return
122
+ end
90
123
124
+ """
125
+ Creates a temporary context for `device` and executes `f(context)` while this context is active.
126
+ Context gets destroyed afterwards. Note, that creating a temporary context is expensive.
127
+ """
128
+ function on_device (f, device = current_device ())
129
+ ctx = new_context (device)
130
+ f (ctx)
131
+ destroy! (ctx)
132
+ return
133
+ end
134
+
135
+ """
136
+ Returns all devices for the current backend.
137
+ Can be filtered by passing `filter_funcs`, e.g. `is_gpu`, `is_cpu`, `(dev)-> has_atleast(dev, threads, 512)`
138
+ """
139
+ function available_devices (filter_funcs... )
140
+ result = []
141
+ for device in current_backend (). devices ()
142
+ if all (f-> f (device), filter_funcs)
143
+ push! (result, device)
144
+ end
145
+ end
146
+ result
147
+ end
91
148
92
149
93
- function devices (filter_funcs... )
150
+ """
151
+ Returns all devices from `backends = active_backends()`.
152
+ Can be filtered by passing `filter_funcs`, e.g. `is_gpu`, `is_cpu`, `dev-> has_atleast(dev, threads, 512)`
153
+ """
154
+ function all_devices (filter_funcs... ; backends = active_backends ())
94
155
result = []
95
- for Module in backend_modules ()
156
+ for Module in backends
96
157
for device in Module. devices ()
97
158
if all (f-> f (device), filter_funcs)
98
159
push! (result, device)
@@ -113,11 +174,11 @@ function perbackend(f)
113
174
end
114
175
115
176
"""
116
- Iterates through all available devices and calls `f` after initializing the current one!
177
+ Iterates through all available devices and calls `f(context) ` after initializing the standard context for that device.
117
178
"""
118
179
function forall_devices (f, filterfuncs... )
119
- for device in devices (filterfunc)
120
- make_current (device)
121
- f (device )
180
+ for device in all_devices (filterfunc... )
181
+ ctx = init (device)
182
+ f (ctx )
122
183
end
123
184
end
0 commit comments