@@ -58,6 +58,55 @@ def _gen_sample_profile_event(
58
58
end_time = time [1 ],
59
59
)
60
60
61
+ @staticmethod
62
+ def _gen_sample_debug_event (
63
+ instruction_id : int ,
64
+ delegate_debug_id : Optional [Union [int , str ]] = None ,
65
+ ) -> flatcc .DebugEvent :
66
+ """
67
+ Helper for generating test DebugEvents
68
+
69
+ Notably:
70
+ - delegate_debug_id takes either the str or int representation
71
+ """
72
+ delegate_debug_id_int = (
73
+ delegate_debug_id if isinstance (delegate_debug_id , int ) else - 1
74
+ )
75
+ delegate_debug_id_str = (
76
+ delegate_debug_id if isinstance (delegate_debug_id , str ) else ""
77
+ )
78
+
79
+ return flatcc .DebugEvent (
80
+ chain_index = 0 ,
81
+ instruction_id = instruction_id ,
82
+ delegate_debug_id_int = delegate_debug_id_int ,
83
+ delegate_debug_id_str = delegate_debug_id_str ,
84
+ debug_entry = flatcc .Value (
85
+ val = flatcc .ValueType .TENSOR .value ,
86
+ tensor = flatcc .Tensor (
87
+ scalar_type = flatcc .ScalarType .INT ,
88
+ sizes = [1 ],
89
+ strides = [1 ],
90
+ offset = 12345 ,
91
+ ),
92
+ tensor_list = flatcc .TensorList (
93
+ [
94
+ flatcc .Tensor (
95
+ scalar_type = flatcc .ScalarType .INT ,
96
+ sizes = [1 ],
97
+ strides = [1 ],
98
+ offset = 12345 ,
99
+ )
100
+ ]
101
+ ),
102
+ int_value = flatcc .Int (1 ),
103
+ float_value = flatcc .Float (1.0 ),
104
+ double_value = flatcc .Double (1.0 ),
105
+ bool_value = flatcc .Bool (False ),
106
+ output = None ,
107
+ ),
108
+ )
109
+
61
110
@staticmethod
62
111
def _get_sample_etdump_flatcc () -> flatcc .ETDumpFlatCC :
63
112
"""
@@ -123,17 +172,145 @@ def _get_sample_etdump_flatcc() -> flatcc.ETDumpFlatCC:
123
172
124
173
return ETDumpFlatCC (version = 0 , run_data = [run_data_1 , run_data_2 , run_data_3 ])
125
174
175
+ @staticmethod
176
+ def _get_sample_etdump_flatcc_inconsistent_debug_data () -> flatcc .ETDumpFlatCC :
177
+ debug_event_1 = TestEventBlock ._gen_sample_debug_event (
178
+ instruction_id = 1 , delegate_debug_id = 100
179
+ )
180
+ run_data_1 = flatcc .RunData (
181
+ name = "signature_a" ,
182
+ bundled_input_index = - 1 ,
183
+ allocators = [],
184
+ events = [
185
+ flatcc .Event (
186
+ allocation_event = None ,
187
+ debug_event = debug_event_1 ,
188
+ profile_event = None ,
189
+ ),
190
+ ],
191
+ )
192
+
193
+ debug_event_2 = TestEventBlock ._gen_sample_debug_event (
194
+ instruction_id = 1 , delegate_debug_id = 100
195
+ )
196
+ # Modify this debug event so it's different from debug_event_1
197
+ debug_event_2 .debug_entry .tensor .sizes = [2 ] # pyre-ignore
198
+ run_data_2 = flatcc .RunData (
199
+ name = "signature_a" ,
200
+ bundled_input_index = - 1 ,
201
+ allocators = [],
202
+ events = [
203
+ flatcc .Event (
204
+ allocation_event = None ,
205
+ debug_event = debug_event_2 ,
206
+ profile_event = None ,
207
+ ),
208
+ ],
209
+ )
210
+ return ETDumpFlatCC (version = 0 , run_data = [run_data_1 , run_data_2 ])
211
+
212
+ @staticmethod
213
+ def _get_sample_etdump_flatcc_profiling_and_debugging () -> flatcc .ETDumpFlatCC :
214
+ """
215
+ Helper for getting a sample ETDumpFlatCC object with 3 RunData:
216
+ - run_data_1 has signature_a with (debug_event_1, profile_event_1)
217
+ - run_data_2 has the same signature with run_data_1 and same debug event, but different profiling times
218
+ - run_data_3 has signature_b with (debug_event_3, profile_event_3) and (not debug event, profile_event_4)
219
+ """
220
+ profile_event_1 = TestEventBlock ._gen_sample_profile_event (
221
+ name = "profile_1" , instruction_id = 1 , time = (0 , 1 ), delegate_debug_id = 100
222
+ )
223
+ debug_event_1 = TestEventBlock ._gen_sample_debug_event (
224
+ instruction_id = 1 , delegate_debug_id = 100
225
+ )
226
+ run_data_1 = flatcc .RunData (
227
+ name = "signature_a" ,
228
+ bundled_input_index = - 1 ,
229
+ allocators = [],
230
+ events = [
231
+ flatcc .Event (
232
+ allocation_event = None ,
233
+ debug_event = None ,
234
+ profile_event = profile_event_1 ,
235
+ ),
236
+ flatcc .Event (
237
+ allocation_event = None ,
238
+ debug_event = debug_event_1 ,
239
+ profile_event = None ,
240
+ ),
241
+ ],
242
+ )
243
+
244
+ profile_event_2 = TestEventBlock ._gen_sample_profile_event (
245
+ name = "profile_1" , instruction_id = 1 , time = (2 , 4 ), delegate_debug_id = 100
246
+ )
247
+ debug_event_2 = TestEventBlock ._gen_sample_debug_event (
248
+ instruction_id = 1 , delegate_debug_id = 100
249
+ )
250
+ run_data_2 = flatcc .RunData (
251
+ name = "signature_a" ,
252
+ bundled_input_index = - 1 ,
253
+ allocators = [],
254
+ events = [
255
+ flatcc .Event (
256
+ allocation_event = None ,
257
+ debug_event = None ,
258
+ profile_event = profile_event_2 ,
259
+ ),
260
+ flatcc .Event (
261
+ allocation_event = None ,
262
+ debug_event = debug_event_2 ,
263
+ profile_event = None ,
264
+ ),
265
+ ],
266
+ )
267
+
268
+ profile_event_3 = TestEventBlock ._gen_sample_profile_event (
269
+ name = "profile_3" , instruction_id = 1 , time = (5 , 6 ), delegate_debug_id = 100
270
+ )
271
+ debug_event_3 = TestEventBlock ._gen_sample_debug_event (
272
+ instruction_id = 1 , delegate_debug_id = 100
273
+ )
274
+ profile_event_4 = TestEventBlock ._gen_sample_profile_event (
275
+ name = "profile_4" , instruction_id = 2 , time = (7 , 8 ), delegate_debug_id = 100
276
+ )
277
+ run_data_3 = flatcc .RunData (
278
+ name = "signature_b" ,
279
+ bundled_input_index = - 1 ,
280
+ allocators = [],
281
+ events = [
282
+ flatcc .Event (
283
+ allocation_event = None ,
284
+ debug_event = debug_event_3 ,
285
+ profile_event = None ,
286
+ ),
287
+ flatcc .Event (
288
+ allocation_event = None ,
289
+ debug_event = None ,
290
+ profile_event = profile_event_3 ,
291
+ ),
292
+ flatcc .Event (
293
+ allocation_event = None ,
294
+ debug_event = None ,
295
+ profile_event = profile_event_4 ,
296
+ ),
297
+ ],
298
+ )
299
+
300
+ return ETDumpFlatCC (version = 0 , run_data = [run_data_1 , run_data_2 , run_data_3 ])
301
+
126
302
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Tests ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
127
303
128
304
def test_gen_from_etdump (self ) -> None :
129
305
"""
130
306
Test "e2e" generation of EventBlocks given an ETDump
131
- - Generated via EventBock .gen_from_etdump
307
+ - Generated via EventBlock .gen_from_etdump
132
308
133
309
Specifically it tests for external correctness:
134
310
- Correct number of EventBlocks
135
311
- Correct number of Events and Raw Data values (iterations)
136
312
"""
313
+
137
314
etdump : ETDumpFlatCC = TestEventBlock ._get_sample_etdump_flatcc ()
138
315
blocks : List [EventBlock ] = EventBlock ._gen_from_etdump (etdump )
139
316
@@ -147,6 +324,52 @@ def test_gen_from_etdump(self) -> None:
147
324
run_counts .add ((len (block .events ), len (perf_data .raw )))
148
325
self .assertSetEqual (run_counts , {(1 , 2 ), (2 , 1 )})
149
326
327
+ def test_gen_from_etdump_profiling_and_debugging (self ) -> None :
328
+ """
329
+ Test "e2e" generation of EventBlocks given an ETDump with both profiling and debugging events
330
+ - Generated via EventBlock.gen_from_etdump
331
+
332
+ Specifically it tests for external correctness:
333
+ - Correct number of EventBlocks
334
+ - Correct number of raw perf_data and debug_data for each Event
335
+ """
336
+ etdump : ETDumpFlatCC = (
337
+ TestEventBlock ._get_sample_etdump_flatcc_profiling_and_debugging ()
338
+ )
339
+ blocks : List [EventBlock ] = EventBlock ._gen_from_etdump (etdump )
340
+
341
+ self .assertEqual (len (blocks ), 2 , f"Expected 2 runs, got { len (blocks )} " )
342
+
343
+ # One EventBlock should have 1 event with 2 iterations
344
+ # and 1 debug data (because we only populate debug data in the first iteration)
345
+ self .assertEqual (len (blocks [0 ].events ), 1 )
346
+ if (perf_data := blocks [0 ].events [0 ].perf_data ) is not None :
347
+ self .assertEqual (len (perf_data .raw ), 2 )
348
+ self .assertEqual (len (blocks [0 ].events [0 ].debug_data ), 1 )
349
+
350
+ # The other EventBlock should have 2 events with 1 iterations, and only the fist event has debug data
351
+ self .assertEqual (len (blocks [1 ].events ), 2 )
352
+ perf_data = blocks [1 ].events [0 ].perf_data
353
+ self .assertIsNotNone (perf_data )
354
+ self .assertEqual (len (perf_data .raw ), 1 )
355
+
356
+ perf_data = blocks [1 ].events [1 ].perf_data
357
+ self .assertIsNotNone (perf_data )
358
+ self .assertEqual (len (perf_data .raw ), 1 )
359
+ self .assertEqual (len (blocks [1 ].events [0 ].debug_data ), 1 )
360
+ self .assertEqual (len (blocks [1 ].events [1 ].debug_data ), 0 )
361
+
362
+ def test_gen_from_etdump_inconsistent_debug_data (self ) -> None :
363
+ """
364
+ Make sure AssertionError is thrown when intermediate outputs are different across
365
+ different iterations of a model run
366
+ """
367
+ etdump : ETDumpFlatCC = (
368
+ TestEventBlock ._get_sample_etdump_flatcc_inconsistent_debug_data ()
369
+ )
370
+ with self .assertRaises (AssertionError ):
371
+ EventBlock ._gen_from_etdump (etdump )
372
+
150
373
def test_inspector_event_generation (self ) -> None :
151
374
"""
152
375
Test Inspector.Event derivation from various ProfileEvent cases
@@ -187,7 +410,8 @@ def _test_profile_event_generation(
187
410
self .assertEqual (profile_signature , expected_signature )
188
411
189
412
event_signature = EventSignature (
190
- instruction_id = instruction_id , profile_event_signature = profile_signature
413
+ instruction_id = instruction_id ,
414
+ profile_event_signature = profile_signature ,
191
415
)
192
416
193
417
# Test Event Generation
0 commit comments