forked from JuliaGPU/GPUArrays.jl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdevices.jl
168 lines (140 loc) · 3.71 KB
/
devices.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
"""
Hardware threads of device
"""
threads(device) = 0
"""
Blocks that group together hardware threads
"""
blocks(device) = 1
"""
Global memory, e.g. VRAM or RAM of device
"""
global_memory(device) = 0
"""
Free global memory. Isn't supported for AMD cards right now, in which case it returns NaN,
so don't rely on the output of this function.
"""
free_global_memory(device) = NaN
"""
Block local memory
"""
local_memory(device) = 0
"""
Hardware name of a device
"""
name(device) = "Undefined"
"""
Summarizes all features of a device and prints it to `io`
"""
function device_summary(io::IO, device)
println(io, "Device: ", name(device))
for (n, f) in (:threads => threads, :blocks => blocks)
@printf(io, "%19s: %s\n", string(n), string(f(device)))
end
for (n, f) in (:global_memory => global_memory, :free_global_memory => free_global_memory, :local_memory => local_memory)
@printf(io, "%19s: %f mb\n", string(n), f(device) / 10^6)
end
return
end
################################
# Device selection functions for e.g. devices(filterfuncs)
"""
Returns true if `device` is a gpu
"""
is_gpu(device) = false
"""
Returns true if `device` is a cpu
"""
is_cpu(device) = false
"""
Checks a device for a certain attribute and returns true if it has at least `value`.
Can be used with e.g. `threads`, `blocks`, `global_memory`, `local_memory`
"""
has_atleast(device, attribute, value) = attribute(ctx_or_device) >= value
#################################
# Context filter functions
# Works for context objects as well but is overloaded in the backends
is_opencl(ctx::Symbol) = ctx == :opencl
is_cudanative(ctx::Symbol) = ctx == :cudanative
is_julia(ctx::Symbol) = ctx == :threaded
is_opengl(ctx::Symbol) = ctx == :opengl
is_opencl(ctx) = false
is_cudanative(ctx) = false
is_julia(ctx) = false
is_opengl(ctx) = false
supports_double(ctx) = false
#=
Functions to select contexts
=#
"""
Creates a new context from `device` without caching the resulting context.
"""
function new_context(device)
error("Device $device not supported")
end
"""
Destroys context, freeing all it's resources.
"""
function destroy!(context)
error("Device $context not supported")
end
"""
Resets a context freeing all resources and creating a new context.
"""
function reset!(context)
error("Context $context not supported")
end
"""
Creates a temporary context for `device` and executes `f(context)` while this context is active.
Context gets destroyed afterwards. Note, that creating a temporary context is expensive.
"""
function on_device(f, device = current_device())
ctx = new_context(device)
try
f(ctx)
finally
destroy!(ctx)
end
return
end
const filterfuncs = """
Device can be filtered by passing `filter_funcs`, e.g. :
`is_gpu`, `is_cpu`, `(dev)-> has_atleast(dev, threads, 512)`
"""
"""
Returns all devices for the current backend.
$filterfuncs
"""
function available_devices(filter_funcs...)
result = []
for device in current_backend().devices()
if all(f-> f(device), filter_funcs)
push!(result, device)
end
end
result
end
"""
Returns all devices from `backends = active_backends()`.
$filterfuncs
"""
function all_devices(filter_funcs...; backends = active_backends())
result = []
for Module in backends
for device in Module.devices()
if all(f-> f(device), filter_funcs)
push!(result, device)
end
end
end
result
end
"""
Iterates through all available devices and calls `f(context)` after initializing the standard context for that device.
"""
function forall_devices(func, filterfuncs...)
for device in all_devices(filterfuncs...)
ctx = init(device)
func(ctx)
end
end