| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- /* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ==============================================================================*/
- #ifndef TENSORFLOW_LITE_CORE_API_PROFILER_H_
- #define TENSORFLOW_LITE_CORE_API_PROFILER_H_
- #include <cstdint>
- namespace tflite {
- // A simple utility for enabling profiled event tracing in TensorFlow Lite.
- class Profiler {
- public:
- // As certain Profiler instance might be only interested in certain event
- // types, we define each event type value to allow a Profiler to use
- // bitmasking bitwise operations to determine whether an event should be
- // recorded or not.
- enum class EventType {
- // Default event type, the metadata field has no special significance.
- DEFAULT = 1,
- // The event is an operator invocation and the event_metadata field is the
- // index of operator node.
- OPERATOR_INVOKE_EVENT = 2,
- // The event is an invocation for an internal operator of a TFLite delegate.
- // The event_metadata field is the index of operator node that's specific to
- // the delegate.
- DELEGATE_OPERATOR_INVOKE_EVENT = 4,
- // The event is a recording of runtime instrumentation such as the overall
- // TFLite runtime status, the TFLite delegate status (if a delegate
- // is applied), and the overall model inference latency etc.
- // Note, the delegate status and overall status are stored as separate
- // event_metadata fields. In particular, the delegate status is encoded
- // as DelegateStatus::full_status().
- GENERAL_RUNTIME_INSTRUMENTATION_EVENT = 8,
- };
- virtual ~Profiler() {}
- // Signals the beginning of an event and returns a handle to the profile
- // event. The `event_metadata1` and `event_metadata2` have different
- // interpretations based on the actual Profiler instance and the `event_type`.
- // For example, as for the 'SubgraphAwareProfiler' defined in
- // lite/core/subgraph.h, when the event_type is OPERATOR_INVOKE_EVENT,
- // `event_metadata1` represents the index of a TFLite node, and
- // `event_metadata2` represents the index of the subgraph that this event
- // comes from.
- virtual uint32_t BeginEvent(const char* tag, EventType event_type,
- int64_t event_metadata1,
- int64_t event_metadata2) = 0;
- // Similar w/ the above, but `event_metadata2` defaults to 0.
- uint32_t BeginEvent(const char* tag, EventType event_type,
- int64_t event_metadata) {
- return BeginEvent(tag, event_type, event_metadata, /*event_metadata2*/ 0);
- }
- // Signals an end to the specified profile event with 'event_metadata's, This
- // is useful when 'event_metadata's are not available when the event begins
- // or when one wants to overwrite the 'event_metadata's set at the beginning.
- virtual void EndEvent(uint32_t event_handle, int64_t event_metadata1,
- int64_t event_metadata2) {}
- // Signals an end to the specified profile event.
- virtual void EndEvent(uint32_t event_handle) = 0;
- // Appends an event of type 'event_type' with 'tag' and 'event_metadata'
- // which started at 'start' and ended at 'end'
- // Note:
- // In cases were ProfileSimmarizer and tensorflow::StatsCalculator are used
- // they assume the value is in "usec", if in any case subclasses
- // didn't put usec, then the values are not meaningful.
- // TODO karimnosseir: Revisit and make the function more clear.
- void AddEvent(const char* tag, EventType event_type, uint64_t start,
- uint64_t end, int64_t event_metadata) {
- AddEvent(tag, event_type, start, end, event_metadata,
- /*event_metadata2*/ 0);
- }
- virtual void AddEvent(const char* tag, EventType event_type, uint64_t start,
- uint64_t end, int64_t event_metadata1,
- int64_t event_metadata2) {}
- protected:
- friend class ScopedProfile;
- };
- // Adds a profile event to `profiler` that begins with the construction
- // of the object and ends when the object goes out of scope.
- // The lifetime of tag should be at least the lifetime of `profiler`.
- // `profiler` may be null, in which case nothing is profiled.
- class ScopedProfile {
- public:
- ScopedProfile(Profiler* profiler, const char* tag,
- Profiler::EventType event_type = Profiler::EventType::DEFAULT,
- int64_t event_metadata = 0)
- : profiler_(profiler), event_handle_(0) {
- if (profiler) {
- event_handle_ = profiler_->BeginEvent(tag, event_type, event_metadata);
- }
- }
- ~ScopedProfile() {
- if (profiler_) {
- profiler_->EndEvent(event_handle_);
- }
- }
- protected:
- Profiler* profiler_;
- uint32_t event_handle_;
- };
- class ScopedOperatorProfile : public ScopedProfile {
- public:
- ScopedOperatorProfile(Profiler* profiler, const char* tag, int node_index)
- : ScopedProfile(profiler, tag, Profiler::EventType::OPERATOR_INVOKE_EVENT,
- static_cast<uint32_t>(node_index)) {}
- };
- class ScopedDelegateOperatorProfile : public ScopedProfile {
- public:
- ScopedDelegateOperatorProfile(Profiler* profiler, const char* tag,
- int node_index)
- : ScopedProfile(profiler, tag,
- Profiler::EventType::DELEGATE_OPERATOR_INVOKE_EVENT,
- static_cast<uint32_t>(node_index)) {}
- };
- class ScopedRuntimeInstrumentationProfile : public ScopedProfile {
- public:
- ScopedRuntimeInstrumentationProfile(Profiler* profiler, const char* tag)
- : ScopedProfile(
- profiler, tag,
- Profiler::EventType::GENERAL_RUNTIME_INSTRUMENTATION_EVENT, -1) {}
- void set_runtime_status(int64_t delegate_status, int64_t interpreter_status) {
- if (profiler_) {
- delegate_status_ = delegate_status;
- interpreter_status_ = interpreter_status;
- }
- }
- ~ScopedRuntimeInstrumentationProfile() {
- if (profiler_) {
- profiler_->EndEvent(event_handle_, delegate_status_, interpreter_status_);
- }
- }
- private:
- int64_t delegate_status_;
- int64_t interpreter_status_;
- };
- } // namespace tflite
- #define TFLITE_VARNAME_UNIQ_IMPL(name, ctr) name##ctr
- #define TFLITE_VARNAME_UNIQ(name, ctr) TFLITE_VARNAME_UNIQ_IMPL(name, ctr)
- #define TFLITE_SCOPED_TAGGED_DEFAULT_PROFILE(profiler, tag) \
- tflite::ScopedProfile TFLITE_VARNAME_UNIQ(_profile_, __COUNTER__)( \
- (profiler), (tag))
- #define TFLITE_SCOPED_TAGGED_OPERATOR_PROFILE(profiler, tag, node_index) \
- tflite::ScopedOperatorProfile TFLITE_VARNAME_UNIQ(_profile_, __COUNTER__)( \
- (profiler), (tag), (node_index))
- #define TFLITE_SCOPED_DELEGATE_OPERATOR_PROFILE(profiler, tag, node_index) \
- tflite::ScopedDelegateOperatorProfile TFLITE_VARNAME_UNIQ( \
- _profile_, __COUNTER__)((profiler), (tag), (node_index))
- #define TFLITE_ADD_RUNTIME_INSTRUMENTATION_EVENT( \
- profiler, tag, delegate_status, interpreter_status) \
- do { \
- if (!profiler) { \
- const auto handle = profiler->BeginEvent( \
- tag, Profiler::EventType::GENERAL_RUNTIME_INSTRUMENTATION_EVENT, \
- delegate_status, interpreter_status); \
- profiler->EndEvent(handle); \
- } \
- } while (false);
- #endif // TENSORFLOW_LITE_CORE_API_PROFILER_H_
|