Skip to content

Commit 9602572

Browse files
tarun292facebook-github-bot
authored andcommitted
Add option to disable operator profiling
Summary: For smaller models the overhead of profiling ops might be prohibitively large (distorting the inference execution time significantly) so we provide users an option to disable op profiling and essentially only profile the important events such as inference execution time. To disable operator profiling users need to do: ``` etdump_gen.set_event_tracer_profiling_level(executorch::runtime::EventTracerProfilingLevel::kNoOperatorProfiling); ``` Differential Revision: D61883224
1 parent bdaeede commit 9602572

File tree

4 files changed

+146
-11
lines changed

4 files changed

+146
-11
lines changed

runtime/core/event_tracer.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,13 @@ enum class EventTracerDebugLogLevel {
6767
kIntermediateOutputs,
6868
};
6969

70+
enum class EventTracerProfilingLevel {
71+
/// No operator profiling.
72+
kNoOperatorProfiling,
73+
/// All profiling events enabled.
74+
kProfileAllEvents,
75+
};
76+
7077
/**
7178
* This is the struct which should be returned when a profiling event is
7279
* started. This is used to uniquely identify that profiling event and will be
@@ -423,6 +430,22 @@ class EventTracer {
423430
return event_tracer_debug_level_;
424431
}
425432

433+
/**
434+
* Set the level of event tracer profiling that is desired.
435+
*
436+
*/
437+
void set_event_tracer_profiling_level(
438+
EventTracerProfilingLevel profiling_level) {
439+
event_tracer_profiling_level_ = profiling_level;
440+
}
441+
442+
/**
443+
* Return the current level of event tracer profiling.
444+
*/
445+
EventTracerProfilingLevel event_tracer_profiling_level() {
446+
return event_tracer_profiling_level_;
447+
}
448+
426449
/**
427450
* Return the current status of intermediate outputs logging mode.
428451
*/
@@ -458,6 +481,8 @@ class EventTracer {
458481
int bundled_input_index_ = kUnsetBundledInputIndex;
459482
EventTracerDebugLogLevel event_tracer_debug_level_ =
460483
EventTracerDebugLogLevel::kNoLogging;
484+
EventTracerProfilingLevel event_tracer_profiling_level_ =
485+
EventTracerProfilingLevel::kProfileAllEvents;
461486
};
462487

463488
} // namespace runtime

runtime/core/event_tracer_hooks.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,48 @@ namespace executorch {
3333
namespace runtime {
3434
namespace internal {
3535

36+
/**
37+
* This class enables scope based profiling where needed using RAII.
38+
* Profiling will be started when the object is created and will end
39+
* when the object goes out of scope.
40+
*/
41+
class EventTracerOpProfileScope final {
42+
public:
43+
EventTracerOpProfileScope(EventTracer* event_tracer, const char* name) {
44+
#ifdef ET_EVENT_TRACER_ENABLED
45+
event_tracer_ = event_tracer;
46+
if (event_tracer_ == nullptr) {
47+
return;
48+
}
49+
if (event_tracer_->event_tracer_profiling_level() >
50+
executorch::runtime::EventTracerProfilingLevel::kNoOperatorProfiling) {
51+
event_entry_ = event_tracer->start_profiling(name);
52+
}
53+
#else //! ET_EVENT_TRACER_ENABLED
54+
(void)event_tracer;
55+
(void)name;
56+
#endif
57+
}
58+
59+
~EventTracerOpProfileScope() {
60+
#ifdef ET_EVENT_TRACER_ENABLED
61+
if (event_tracer_ == nullptr) {
62+
return;
63+
}
64+
if (event_tracer_->event_tracer_profiling_level() >
65+
executorch::runtime::EventTracerProfilingLevel::kNoOperatorProfiling) {
66+
event_tracer_->end_profiling(event_entry_);
67+
}
68+
#endif
69+
}
70+
71+
private:
72+
#ifdef ET_EVENT_TRACER_ENABLED
73+
EventTracer* event_tracer_;
74+
EventTracerEntry event_entry_;
75+
#endif
76+
};
77+
3678
/**
3779
* This class enables scope based profiling where needed using RAII.
3880
* Profiling will be started when the object is created and will end
@@ -111,6 +153,13 @@ class EventTracerProfileInstructionScope final {
111153
#endif
112154
};
113155

156+
inline bool event_tracer_enabled() {
157+
#ifdef ET_EVENT_TRACER_ENABLED
158+
return true;
159+
#else //! ET_EVENT_TRACER_ENABLED
160+
return false;
161+
#endif
162+
}
114163
/**
115164
* Create a new event block with the specified name. Any events logged
116165
* after this will be associated with this new event block.

runtime/core/test/event_tracer_test.cpp

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,15 @@ class DummyEventTracer : public EventTracer {
4444
const char* name,
4545
ChainID chain_id = kUnsetChainId,
4646
DebugHandle debug_handle = kUnsetDebugHandle) override {
47-
(void)name;
4847
(void)chain_id;
4948
(void)debug_handle;
49+
memcpy(event_name_, name, strlen(name) + 1);
5050
return EventTracerEntry();
5151
}
5252

5353
void end_profiling(EventTracerEntry prof_entry) override {
5454
(void)prof_entry;
55+
memset(event_name_, 0, sizeof(event_name_));
5556
return;
5657
}
5758

@@ -156,13 +157,22 @@ class DummyEventTracer : public EventTracer {
156157
return logged_evalue_type_;
157158
}
158159

160+
char* get_event_name() {
161+
return event_name_;
162+
}
163+
164+
void reset_event_name() {
165+
memset(event_name_, 0, sizeof(event_name_));
166+
}
167+
159168
void reset_logged_value() {
160169
logged_evalue_ = EValue(false);
161170
}
162171

163172
private:
164173
EValue logged_evalue_ = EValue(false);
165174
LoggedEValueType logged_evalue_type_;
175+
char event_name_[1024];
166176
};
167177

168178
/**
@@ -282,3 +292,54 @@ TEST(TestEventTracer, SimpleEventTracerTestLogging) {
282292

283293
// TODO(T163645377): Add more test coverage to log and verify events passed into
284294
// DummyTracer.
295+
TEST(TestEventTracer, EventTracerOpProfileControl) {
296+
DummyEventTracer dummy;
297+
// Op profiling is enabled by default. Test that it works.
298+
{
299+
{
300+
executorch::runtime::internal::EventTracerOpProfileScope
301+
event_tracer_op_scope(&dummy, "ExampleOpScope");
302+
EXPECT_EQ(
303+
memcmp(
304+
dummy.get_event_name(),
305+
"ExampleOpScope",
306+
strlen("ExampleOpScope")),
307+
0);
308+
}
309+
EXPECT_EQ(memcmp(dummy.get_event_name(), "", 1), 0);
310+
311+
// Normal profiling should still work.
312+
{
313+
executorch::runtime::internal::EventTracerProfileScope
314+
event_tracer_profiler_scope(&dummy, "ExampleProfilerScope");
315+
EXPECT_EQ(
316+
memcmp(
317+
dummy.get_event_name(),
318+
"ExampleProfilerScope",
319+
strlen("ExampleProfilerScope")),
320+
0);
321+
}
322+
323+
dummy.set_event_tracer_profiling_level(
324+
executorch::runtime::EventTracerProfilingLevel::kNoOperatorProfiling);
325+
326+
// Op profiling should be disabled now.
327+
{
328+
executorch::runtime::internal::EventTracerOpProfileScope
329+
event_tracer_op_scope(&dummy, "ExampleOpScope");
330+
EXPECT_EQ(memcmp(dummy.get_event_name(), "", 1), 0);
331+
}
332+
333+
// Normal profiling should still work.
334+
{
335+
executorch::runtime::internal::EventTracerProfileScope
336+
event_tracer_profiler_scope(&dummy, "1ExampleProfilerScope");
337+
EXPECT_EQ(
338+
memcmp(
339+
dummy.get_event_name(),
340+
"1ExampleProfilerScope",
341+
strlen("1ExampleProfilerScope")),
342+
0);
343+
}
344+
}
345+
}

runtime/executor/method.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,8 +1022,8 @@ Error Method::execute_instruction() {
10221022
switch (instruction->instr_args_type()) {
10231023
case executorch_flatbuffer::InstructionArguments::KernelCall: {
10241024
EXECUTORCH_SCOPE_PROF("OPERATOR_CALL");
1025-
internal::EventTracerProfileScope event_tracer_scope =
1026-
internal::EventTracerProfileScope(event_tracer_, "OPERATOR_CALL");
1025+
internal::EventTracerOpProfileScope event_tracer_op_scope =
1026+
internal::EventTracerOpProfileScope(event_tracer_, "OPERATOR_CALL");
10271027
// TODO(T147221312): Also expose tensor resizer via the context.
10281028
KernelRuntimeContext context(event_tracer_, temp_allocator_);
10291029
auto args = chain.argument_lists_[step_state_.instr_idx];
@@ -1057,8 +1057,8 @@ Error Method::execute_instruction() {
10571057
} break;
10581058
case executorch_flatbuffer::InstructionArguments::DelegateCall: {
10591059
EXECUTORCH_SCOPE_PROF("DELEGATE_CALL");
1060-
internal::EventTracerProfileScope event_tracer_profile_scope =
1061-
internal::EventTracerProfileScope(event_tracer_, "DELEGATE_CALL");
1060+
internal::EventTracerOpProfileScope event_tracer_op_scope =
1061+
internal::EventTracerOpProfileScope(event_tracer_, "DELEGATE_CALL");
10621062
// We know that instr_args_as_DelegateCall is non-null because it was
10631063
// checked at init time.
10641064
auto delegate_idx =
@@ -1101,8 +1101,8 @@ Error Method::execute_instruction() {
11011101
} break;
11021102
case executorch_flatbuffer::InstructionArguments::JumpFalseCall: {
11031103
EXECUTORCH_SCOPE_PROF("JF_CALL");
1104-
internal::EventTracerProfileScope event_tracer_profile_scope =
1105-
internal::EventTracerProfileScope(event_tracer_, "JF_CALL");
1104+
internal::EventTracerOpProfileScope event_tracer_op_scope =
1105+
internal::EventTracerOpProfileScope(event_tracer_, "JF_CALL");
11061106
// We know that instr_args_as_JumpFalseCall is non-null because it was
11071107
// checked at init time.
11081108
auto jf_call = instruction->instr_args_as_JumpFalseCall();
@@ -1120,17 +1120,17 @@ Error Method::execute_instruction() {
11201120
} break;
11211121
case executorch_flatbuffer::InstructionArguments::MoveCall: {
11221122
EXECUTORCH_SCOPE_PROF("MOVE_CALL");
1123-
internal::EventTracerProfileScope event_tracer_profile_scope =
1124-
internal::EventTracerProfileScope(event_tracer_, "MOVE_CALL");
1123+
internal::EventTracerOpProfileScope event_tracer_op_scope =
1124+
internal::EventTracerOpProfileScope(event_tracer_, "MOVE_CALL");
11251125
// We know that instr_args_as_MoveCall is non-null because it was checked
11261126
// at init time.
11271127
auto move_call = instruction->instr_args_as_MoveCall();
11281128
mutable_value(move_call->move_to()) = get_value(move_call->move_from());
11291129
} break;
11301130
case executorch_flatbuffer::InstructionArguments::FreeCall: {
11311131
EXECUTORCH_SCOPE_PROF("FREE_CALL");
1132-
internal::EventTracerProfileScope event_tracer_profile_scope =
1133-
internal::EventTracerProfileScope(event_tracer_, "FREE_CALL");
1132+
internal::EventTracerOpProfileScope event_tracer_op_scope =
1133+
internal::EventTracerOpProfileScope(event_tracer_, "FREE_CALL");
11341134
// We know that instr_args_as_FreeCall is non-null because it was checked
11351135
// at init time.
11361136
auto free_call = instruction->instr_args_as_FreeCall();

0 commit comments

Comments
 (0)