@@ -5,18 +5,98 @@ function version()
5
5
end
6
6
7
7
8
+ #
9
+ # callback API
10
+ #
11
+
12
+ # multiple subscribers aren't supported, so make sure we only call CUPTI once
13
+ const callback_lock = ReentrantLock ()
14
+
15
+ function callback (userdata:: Ptr{Cvoid} , domain:: CUpti_CallbackDomain ,
16
+ id:: CUpti_CallbackId , data_ptr:: Ptr{Cvoid} )
17
+ cfg = Base. unsafe_pointer_to_objref (userdata):: CallbackConfig
18
+
19
+ # decode the callback data
20
+ datatype = if domain in (CUPTI_CB_DOMAIN_DRIVER_API, CUPTI_CB_DOMAIN_RUNTIME_API)
21
+ CUpti_CallbackData
22
+ elseif domain == CUPTI_CB_DOMAIN_RESOURCE
23
+ CUpti_ResourceData
24
+ elseif domain == CUPTI_CB_DOMAIN_SYNCHRONIZE
25
+ CUpti_SynchronizeData
26
+ elseif domain == CUPTI_CB_DOMAIN_NVTX
27
+ CUpti_NvtxData
28
+ else
29
+ @warn """ Unsupported callback domain: $(domain) .
30
+ Please file an issue, or extend the implementation of `CUPTI.callback` to handle this callback kind."""
31
+ return
32
+ end
33
+ data = unsafe_load (convert (Ptr{datatype}, data_ptr))
34
+
35
+ # invoke the actual user callback
36
+ cfg. callback (domain, id, data)
37
+
38
+ return
39
+ end
40
+
41
+ """
42
+ cfg = CUPTI.CallbackConfig(callback_kinds) do domain, id, data
43
+ # inspect data
44
+ end
45
+
46
+ CUPTI.enable!(cfg) do
47
+ # do stuff
48
+ end
49
+ """
50
+ mutable struct CallbackConfig
51
+ callback:: Function
52
+ callback_kinds:: Vector{CUpti_CallbackDomain}
53
+ end
54
+
55
+ function enable! (f:: Base.Callable , cfg:: CallbackConfig )
56
+ @lock callback_lock begin
57
+ callback_ptr =
58
+ @cfunction (callback, Cvoid,
59
+ (Ptr{Cvoid}, CUpti_CallbackDomain, CUpti_CallbackId, Ptr{Cvoid}))
60
+
61
+ GC. @preserve cfg begin
62
+ # set-up subscriber
63
+ subscriber_ref = Ref {CUpti_SubscriberHandle} ()
64
+ cuptiSubscribe (subscriber_ref, callback_ptr, Base. pointer_from_objref (cfg))
65
+ subscriber = subscriber_ref[]
66
+
67
+ # enable domains
68
+ for callback_kind in cfg. callback_kinds
69
+ CUPTI. cuptiEnableDomain (true , subscriber, callback_kind)
70
+ end
71
+
72
+ try
73
+ f ()
74
+ finally
75
+ # disable callback kinds
76
+ for callback_kind in cfg. callback_kinds
77
+ CUPTI. cuptiEnableDomain (false , subscriber, callback_kind)
78
+ end
79
+
80
+ # disable the subscriber
81
+ CUPTI. cuptiUnsubscribe (subscriber)
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+
8
88
#
9
89
# activity API
10
90
#
11
91
12
92
"""
13
- cfg = ActvitiyConfig (activity_kinds)
93
+ cfg = CUPTI.ActivityConfig (activity_kinds)
14
94
15
- enable!(cfg)
16
- # do stuff
17
- disable!(cfg)
95
+ CUPTI. enable!(cfg) do
96
+ # do stuff
97
+ end
18
98
19
- process(cfg) do ( ctx, stream , record)
99
+ CUPTI. process(cfg) do ctx, stream_id , record
20
100
# inspect record
21
101
end
22
102
@@ -43,6 +123,7 @@ function allocate_buffer()
43
123
Array {UInt8} (undef, 8 * 1024 * 1024 ) # 8 MB
44
124
end
45
125
126
+ const activity_lock = ReentrantLock ()
46
127
const activity_config = Ref {Union{Nothing,ActivityConfig}} (nothing )
47
128
48
129
function request_buffer (dest_ptr, sz_ptr, max_num_records_ptr)
@@ -93,41 +174,40 @@ function complete_buffer(ctx_handle, stream_id, buf_ptr, sz, valid_sz)
93
174
return
94
175
end
95
176
96
- function enable! (cfg:: ActivityConfig )
97
- activity_config[] === nothing ||
98
- error (" Only one profiling session can be active at a time." )
99
-
100
- # set-up callbacks
101
- request_buffer_ptr = @cfunction (request_buffer, Cvoid,
102
- (Ptr{Ptr{UInt8}}, Ptr{Csize_t}, Ptr{Csize_t}))
103
- complete_buffer_ptr = @cfunction (complete_buffer, Cvoid,
104
- (CUDA. CUcontext, UInt32, Ptr{UInt8}, Csize_t, Csize_t))
105
- cuptiActivityRegisterCallbacks (request_buffer_ptr, complete_buffer_ptr)
177
+ function enable! (f:: Base.Callable , cfg:: ActivityConfig )
178
+ @lock activity_lock begin
179
+ activity_config[] = cfg
106
180
107
- activity_config[] = cfg
181
+ # set-up callbacks
182
+ request_buffer_ptr =
183
+ @cfunction (request_buffer, Cvoid,
184
+ (Ptr{Ptr{UInt8}}, Ptr{Csize_t}, Ptr{Csize_t}))
185
+ complete_buffer_ptr =
186
+ @cfunction (complete_buffer, Cvoid,
187
+ (CUDA. CUcontext, UInt32, Ptr{UInt8}, Csize_t, Csize_t))
188
+ cuptiActivityRegisterCallbacks (request_buffer_ptr, complete_buffer_ptr)
108
189
109
- # enable requested activity kinds
110
- for activity_kind in cfg. activity_kinds
111
- cuptiActivityEnable (activity_kind)
112
- end
113
- end
190
+ activity_config[] = cfg
114
191
115
- function disable! (cfg:: ActivityConfig )
116
- if activity_config[] != = cfg
117
- error (" This profiling session is not active." )
118
- end
119
-
120
- # disable activity kinds
121
- for activity_kind in cfg. activity_kinds
122
- cuptiActivityDisable (activity_kind)
123
- end
192
+ # enable requested activity kinds
193
+ for activity_kind in cfg. activity_kinds
194
+ cuptiActivityEnable (activity_kind)
195
+ end
124
196
125
- # flush all activity records, even incomplete ones
126
- cuptiActivityFlushAll (CUPTI_ACTIVITY_FLAG_FLUSH_FORCED)
197
+ try
198
+ f ()
199
+ finally
200
+ # disable activity kinds
201
+ for activity_kind in cfg. activity_kinds
202
+ cuptiActivityDisable (activity_kind)
203
+ end
127
204
128
- activity_config[] = nothing
205
+ # flush all activity records, even incomplete ones
206
+ cuptiActivityFlushAll (CUPTI_ACTIVITY_FLAG_FLUSH_FORCED)
129
207
130
- return
208
+ activity_config[] = nothing
209
+ end
210
+ end
131
211
end
132
212
133
213
function process (f, cfg:: ActivityConfig )
0 commit comments