Skip to content

Commit 9d2aa55

Browse files
Olivia-liufacebook-github-bot
authored andcommitted
Intermediate output logging enablement
Summary: Design doc: https://docs.google.com/document/d/1qGHsgd-roqtxPz4CrUlqGrKaAtbaf9bArziMuwHD0So/edit Differential Revision: D56941407
1 parent 3b5bb00 commit 9d2aa55

File tree

9 files changed

+438
-52
lines changed

9 files changed

+438
-52
lines changed

runtime/core/event_tracer.h

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,106 @@ class EventTracer {
256256
const EValue& evalue,
257257
LoggedEValueType evalue_type) = 0;
258258

259+
/**
260+
* Log an intermediate tensor output from a delegate.
261+
*
262+
* @param[in] name Human readable name for the delegate event. This name has
263+
* to be the same name that was passed in during the Debug delegate mapping
264+
* generation in the export/ahead-of-time process. If indices and not names
265+
* are used by this delegate to identify ops executed in the backend then
266+
* nullptr can be passed in. Users calling this interface do not need to keep
267+
* the memory pointed to by this pointer around. The string must be copied
268+
* over into internal memory during this call.
269+
* @param[in] delegate_debug_index The id of the delegate event. If string
270+
* based names are used by this delegate to identify ops executed in the
271+
* backend then kUnsetDebugHandle should be passed in here.
272+
* @param[in] output The tensor type output to be logged.
273+
*/
274+
virtual void log_intermediate_output_delegate(
275+
const char* name,
276+
DebugHandle delegate_debug_index,
277+
const Tensor& output) = 0;
278+
279+
/**
280+
* Log an intermediate tensor array output from a delegate.
281+
*
282+
* @param[in] name Human readable name for the delegate event. This name has
283+
* to be the same name that was passed in during the Debug delegate mapping
284+
* generation in the export/ahead-of-time process. If indices and not names
285+
* are used by this delegate to identify ops executed in the backend then
286+
* nullptr can be passed in. Users calling this interface do not need to keep
287+
* the memory pointed to by this pointer around. The string must be copied
288+
* over into internal memory during this call.
289+
* @param[in] delegate_debug_index The id of the delegate event. If string
290+
* based names are used by this delegate to identify ops executed in the
291+
* backend then kUnsetDebugHandle should be passed in here.
292+
* @param[in] output The tensor array type output to be logged.
293+
*/
294+
virtual void log_intermediate_output_delegate(
295+
const char* name,
296+
DebugHandle delegate_debug_index,
297+
const ArrayRef<Tensor> output) = 0;
298+
299+
/**
300+
* Log an intermediate int output from a delegate.
301+
*
302+
* @param[in] name Human readable name for the delegate event. This name has
303+
* to be the same name that was passed in during the Debug delegate mapping
304+
* generation in the export/ahead-of-time process. If indices and not names
305+
* are used by this delegate to identify ops executed in the backend then
306+
* nullptr can be passed in. Users calling this interface do not need to keep
307+
* the memory pointed to by this pointer around. The string must be copied
308+
* over into internal memory during this call.
309+
* @param[in] delegate_debug_index The id of the delegate event. If string
310+
* based names are used by this delegate to identify ops executed in the
311+
* backend then kUnsetDebugHandle should be passed in here.
312+
* @param[in] output The int type output to be logged.
313+
*/
314+
virtual void log_intermediate_output_delegate(
315+
const char* name,
316+
DebugHandle delegate_debug_index,
317+
const int& output) = 0;
318+
319+
/**
320+
* Log an intermediate bool output from a delegate.
321+
*
322+
* @param[in] name Human readable name for the delegate event. This name has
323+
* to be the same name that was passed in during the Debug delegate mapping
324+
* generation in the export/ahead-of-time process. If indices and not names
325+
* are used by this delegate to identify ops executed in the backend then
326+
* nullptr can be passed in. Users calling this interface do not need to keep
327+
* the memory pointed to by this pointer around. The string must be copied
328+
* over into internal memory during this call.
329+
* @param[in] delegate_debug_index The id of the delegate event. If string
330+
* based names are used by this delegate to identify ops executed in the
331+
* backend then kUnsetDebugHandle should be passed in here.
332+
* @param[in] output The bool type output to be logged.
333+
*/
334+
virtual void log_intermediate_output_delegate(
335+
const char* name,
336+
DebugHandle delegate_debug_index,
337+
const bool& output) = 0;
338+
339+
/**
340+
* Log an intermediate double output from a delegate.
341+
*
342+
* @param[in] name Human readable name for the delegate event. This name has
343+
* to be the same name that was passed in during the Debug delegate mapping
344+
* generation in the export/ahead-of-time process. If indices and not names
345+
* are used by this delegate to identify ops executed in the backend then
346+
* nullptr can be passed in. Users calling this interface do not need to keep
347+
* the memory pointed to by this pointer around. The string must be copied
348+
* over into internal memory during this call.
349+
* @param[in] delegate_debug_index The id of the delegate event. If string
350+
* based names are used by this delegate to identify ops executed in the
351+
* backend then kUnsetDebugHandle should be passed in here.
352+
* @param[in] output The double type output to be logged.
353+
*/
354+
virtual void log_intermediate_output_delegate(
355+
const char* name,
356+
DebugHandle delegate_debug_index,
357+
const double& output) = 0;
358+
259359
/**
260360
* Helper function to set the chain id ands debug handle. Users have two
261361
* options, the first is that they can directly pass in the chain id and debug

runtime/core/event_tracer_hooks_delegate.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,5 +145,47 @@ inline void event_tracer_log_profiling_delegate(
145145
#endif
146146
}
147147

148+
/**
149+
* This templated interfaces can be called in a loop etc. to log any number of
150+
* debug events that are part of this delegate. Supported values types are int,
151+
* bool, double, tensor and array of tensors. Can be left in production code as
152+
* these hooks compile conditionally.
153+
*
154+
* @param[in] event_tracer The event tracer instance that is doing the logging.
155+
* @param[in] name Human readable name for the delegate event. This name has
156+
* to be the same name that was passed in during the Debug delegate mapping
157+
* generation in the export/ahead-of-time process. If indices and not names
158+
* are used by this delegate to identify ops executed in the backend then
159+
* nullptr can be passed in. Users calling this interface do not need to keep
160+
* the memory pointed to by this pointer around. The string must
161+
* be copied over into internal memory during this call.
162+
* @param[in] delegate_debug_id The id of the delegate event. If string
163+
* based names are used by this delegate to identify ops executed in the
164+
* backend then -1 should be passed in here.
165+
* @param[in] output The output to be logged.
166+
*/
167+
template <typename T>
168+
inline void event_tracer_log_output_delegate(
169+
EventTracer* event_tracer,
170+
const char* name,
171+
DebugHandle delegate_debug_id,
172+
const T& output) {
173+
#ifdef ET_EVENT_TRACER_ENABLED
174+
if (event_tracer) {
175+
static_assert(
176+
std::is_same<T, int>::value || std::is_same<T, bool>::value ||
177+
std::is_same<T, double>::value || std::is_same<T, Tensor>::value ||
178+
std::is_same<T, ArrayRef<Tensor>>::value,
179+
"Unsupported type for intermediate output");
180+
event_tracer->log_intermediate_output_delegate(
181+
name, delegate_debug_id, output);
182+
}
183+
#else //! ET_EVENT_TRACER_ENABLED
184+
(void)name;
185+
(void)delegate_debug_id;
186+
(void)output;
187+
#endif
188+
}
189+
148190
} // namespace executor
149191
} // namespace torch

sdk/etdump/etdump_flatcc.cpp

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,126 @@ void ETDumpGen::log_profiling_delegate(
288288
etdump_RunData_events_push_end(builder);
289289
}
290290

291+
void ETDumpGen::log_intermediate_output_delegate(
292+
const char* name,
293+
DebugHandle delegate_debug_index,
294+
const Tensor& output) {
295+
log_intermediate_output_delegate_helper(name, delegate_debug_index, output);
296+
}
297+
298+
void ETDumpGen::log_intermediate_output_delegate(
299+
const char* name,
300+
DebugHandle delegate_debug_index,
301+
const ArrayRef<Tensor> output) {
302+
log_intermediate_output_delegate_helper(name, delegate_debug_index, output);
303+
}
304+
305+
void ETDumpGen::log_intermediate_output_delegate(
306+
const char* name,
307+
DebugHandle delegate_debug_index,
308+
const int& output) {
309+
log_intermediate_output_delegate_helper(name, delegate_debug_index, output);
310+
}
311+
312+
void ETDumpGen::log_intermediate_output_delegate(
313+
const char* name,
314+
DebugHandle delegate_debug_index,
315+
const bool& output) {
316+
log_intermediate_output_delegate_helper(name, delegate_debug_index, output);
317+
}
318+
319+
void ETDumpGen::log_intermediate_output_delegate(
320+
const char* name,
321+
DebugHandle delegate_debug_index,
322+
const double& output) {
323+
log_intermediate_output_delegate_helper(name, delegate_debug_index, output);
324+
}
325+
326+
template <typename T>
327+
void ETDumpGen::log_intermediate_output_delegate_helper(
328+
const char* name,
329+
DebugHandle delegate_debug_index,
330+
const T& output) {
331+
ET_CHECK_MSG(
332+
(name == nullptr) ^ (delegate_debug_index == -1),
333+
"Only name or delegate_debug_index can be valid. Check DelegateMappingBuilder documentation for more details.");
334+
if (debug_buffer.empty()) {
335+
return;
336+
}
337+
338+
check_ready_to_add_events();
339+
int64_t string_id = name != nullptr ? create_string_entry(name) : -1;
340+
341+
etdump_DebugEvent_start(builder);
342+
343+
etdump_DebugEvent_chain_index_add(builder, chain_id_);
344+
etdump_DebugEvent_instruction_id_add(builder, debug_handle_);
345+
if (string_id == -1) {
346+
etdump_DebugEvent_delegate_debug_id_int_add(builder, delegate_debug_index);
347+
} else {
348+
etdump_DebugEvent_delegate_debug_id_str_add(builder, string_id);
349+
}
350+
351+
// Check the type of `output` then call the corresponding logging functions
352+
if constexpr (std::is_same<T, Tensor>::value) {
353+
long offset = copy_tensor_to_debug_buffer(output);
354+
etdump_Tensor_ref_t tensor_ref = add_tensor_entry(builder, output, offset);
355+
356+
etdump_Value_start(builder);
357+
etdump_Value_val_add(builder, etdump_ValueType_Tensor);
358+
etdump_Value_tensor_add(builder, tensor_ref);
359+
360+
} else if constexpr (std::is_same<T, ArrayRef<Tensor>>::value) {
361+
etdump_Tensor_vec_start(builder);
362+
for (size_t i = 0; i < output.size(); ++i) {
363+
long offset = copy_tensor_to_debug_buffer(output[i]);
364+
etdump_Tensor_vec_push(
365+
builder, add_tensor_entry(builder, output[i], offset));
366+
}
367+
etdump_Tensor_vec_ref_t tensor_vec_ref = etdump_Tensor_vec_end(builder);
368+
etdump_TensorList_ref_t tensor_list_ref =
369+
etdump_TensorList_create(builder, tensor_vec_ref);
370+
371+
etdump_Value_start(builder);
372+
etdump_Value_val_add(builder, etdump_ValueType_TensorList);
373+
etdump_Value_tensor_list_add(builder, tensor_list_ref);
374+
} else if constexpr (std::is_same<T, int>::value) {
375+
auto int_ref = etdump_Int_create(builder, output);
376+
377+
etdump_Value_start(builder);
378+
etdump_Value_val_add(builder, etdump_ValueType_Int);
379+
etdump_Value_int_value_add(builder, int_ref);
380+
} else if constexpr (std::is_same<T, double>::value) {
381+
auto double_ref = etdump_Double_create(builder, output);
382+
383+
etdump_Value_start(builder);
384+
etdump_Value_double_value_add(builder, double_ref);
385+
etdump_Value_val_add(builder, etdump_ValueType_Double);
386+
} else if constexpr (std::is_same<T, bool>::value) {
387+
flatbuffers_bool_t flatbuffer_bool_val =
388+
output ? FLATBUFFERS_TRUE : FLATBUFFERS_FALSE;
389+
auto bool_ref = etdump_Bool_create(builder, flatbuffer_bool_val);
390+
391+
etdump_Value_start(builder);
392+
etdump_Value_bool_value_add(builder, bool_ref);
393+
etdump_Value_val_add(builder, etdump_ValueType_Bool);
394+
} else {
395+
ET_CHECK_MSG(
396+
0,
397+
"This EValue type = %s is not yet supported for logging\n",
398+
typeid(T).name());
399+
}
400+
401+
auto value_ref = etdump_Value_end(builder);
402+
etdump_DebugEvent_debug_entry_add(builder, value_ref);
403+
404+
etdump_DebugEvent_ref_t debug_event = etdump_DebugEvent_end(builder);
405+
406+
etdump_RunData_events_push_start(builder);
407+
etdump_Event_debug_event_add(builder, debug_event);
408+
etdump_RunData_events_push_end(builder);
409+
}
410+
291411
void ETDumpGen::end_profiling(EventTracerEntry prof_entry) {
292412
et_timestamp_t end_time = et_pal_current_ticks();
293413
ET_CHECK_MSG(

sdk/etdump/etdump_flatcc.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,45 @@ class ETDumpGen : public EventTracer {
9797
const EValue& evalue,
9898
LoggedEValueType evalue_type =
9999
LoggedEValueType::kIntermediateOutput) override;
100+
/**
101+
* Log an intermediate tensor output from a delegate.
102+
*/
103+
virtual void log_intermediate_output_delegate(
104+
const char* name,
105+
DebugHandle delegate_debug_index,
106+
const Tensor& output) override;
107+
108+
/**
109+
* Log an intermediate tensor array output from a delegate.
110+
*/
111+
virtual void log_intermediate_output_delegate(
112+
const char* name,
113+
DebugHandle delegate_debug_index,
114+
const ArrayRef<Tensor> output) override;
115+
116+
/**
117+
* Log an intermediate int output from a delegate.
118+
*/
119+
virtual void log_intermediate_output_delegate(
120+
const char* name,
121+
DebugHandle delegate_debug_index,
122+
const int& output) override;
123+
124+
/**
125+
* Log an intermediate bool output from a delegate.
126+
*/
127+
virtual void log_intermediate_output_delegate(
128+
const char* name,
129+
DebugHandle delegate_debug_index,
130+
const bool& output) override;
131+
132+
/**
133+
* Log an intermediate double output from a delegate.
134+
*/
135+
virtual void log_intermediate_output_delegate(
136+
const char* name,
137+
DebugHandle delegate_debug_index,
138+
const double& output) override;
100139
void set_debug_buffer(Span<uint8_t> buffer);
101140
etdump_result get_etdump_data();
102141
size_t get_num_blocks();
@@ -115,6 +154,16 @@ class ETDumpGen : public EventTracer {
115154
void check_ready_to_add_events();
116155
int64_t create_string_entry(const char* name);
117156
size_t copy_tensor_to_debug_buffer(exec_aten::Tensor tensor);
157+
158+
/**
159+
* Templated helper function used to log various types of intermediate output.
160+
* Supported types include tensor, tensor array, int, bool and double.
161+
*/
162+
template <typename T>
163+
void log_intermediate_output_delegate_helper(
164+
const char* name,
165+
DebugHandle delegate_debug_index,
166+
const T& output);
118167
};
119168

120169
} // namespace executor

sdk/etdump/etdump_schema_flatcc.fbs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,12 @@ table DebugEvent {
7070
// The order of these entries is expected to be the same as the parameters
7171
// that are passed into a operator.
7272
debug_entry:Value;
73+
74+
// Integer based delegate debug identifier.
75+
delegate_debug_id_int:int = -1;
76+
77+
// String based delegate debug identifier.
78+
delegate_debug_id_str:string;
7379
}
7480

7581
// All the details pertaining to an allocation done in the runtime. The main

sdk/etdump/schema_flatcc.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ class Value:
9595
class DebugEvent:
9696
chain_index: int
9797
instruction_id: int
98+
delegate_debug_id_int: Optional[int]
99+
delegate_debug_id_str: Optional[str]
98100
debug_entry: Value
99101

100102

sdk/etdump/tests/serialize_test.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ def get_sample_etdump_flatcc() -> flatcc.ETDumpFlatCC:
8585
debug_event=flatcc.DebugEvent(
8686
chain_index=1,
8787
instruction_id=0,
88+
delegate_debug_id_str="56",
89+
delegate_debug_id_int=-1,
8890
debug_entry=flatcc.Value(
8991
val=flatcc.ValueType.TENSOR.value,
9092
tensor=flatcc.Tensor(

0 commit comments

Comments
 (0)