Files

180 lines
5.0 KiB
C++

/* Copyright 2018 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_CONTRIB_LITE_PROFILING_PROFILER_H_
#define TENSORFLOW_CONTRIB_LITE_PROFILING_PROFILER_H_
#include <vector>
#include "tensorflow/contrib/lite/profiling/profile_buffer.h"
#ifdef TFLITE_PROFILING_ENABLED
namespace tflite {
namespace profiling {
class ScopedProfile;
class ScopedOperatorProfile;
// Controls whether profiling is enabled or disabled and collects profiles.
// TFLite is used on platforms that don't have posix threads, so the profiler is
// kept as simple as possible. It is designed to be used only on a single
// thread.
//
// Profiles are collected using Scoped*Profile objects that begin and end a
// profile event.
// An example usage is shown in the example below:
//
// Say Worker class has a DoWork method and we are interested in profiling
// the overall execution time for DoWork and time spent in Task1 and Task2
// functions.
//
// class Worker {
// public:
// void DoWork() {
// ScopedProfile(&controller, "DoWork");
// Task1();
// Task2();
// .....
// }
//
// void Task1() {
// ScopedProfile(&controller, "Task1");
// ....
// }
//
// void Task2() {
// ScopedProfile(&controller, "Task2");
// }
//
// Profiler profiler;
// }
//
// We instrument the functions that need to be profiled.
//
// Profile can be collected by enable profiling and then getting profile
// events.
//
// void ProfileWorker() {
// Worker worker;
// worker.profiler.EnableProfiling();
// worker.DoWork();
// worker.profiler.DisableProfiling();
// // Profiling is complete, extract profiles.
// auto profile_events = worker.profiler.GetProfiles();
// }
//
//
class Profiler {
public:
Profiler() : buffer_(1024, false) {}
void StartProfiling() { buffer_.SetEnabled(true); }
void StopProfiling() { buffer_.SetEnabled(false); }
void Reset() { buffer_.Reset(); }
std::vector<const ProfileEvent*> GetProfileEvents() {
std::vector<const ProfileEvent*> profile_events;
profile_events.reserve(buffer_.Size());
for (size_t i = 0; i < buffer_.Size(); i++) {
profile_events.push_back(buffer_.At(i));
}
return profile_events;
}
private:
friend class ScopedProfile;
friend class ScopedOperatorProfile;
ProfileBuffer* GetProfileBuffer() { return &buffer_; }
ProfileBuffer buffer_;
};
class ScopedProfile {
public:
// Adds a profile event to profile that begins with the construction
// of object and ends when the object goes out of scope.
// The lifetime of tag should be at least the lifetime of profiler.
ScopedProfile(Profiler* profiler, const char* tag)
: buffer_(nullptr), event_handle_(0) {
if (profiler) {
buffer_ = profiler->GetProfileBuffer();
event_handle_ =
buffer_->BeginEvent(tag, ProfileEvent::EventType::DEFAULT, 0);
}
}
~ScopedProfile() {
if (buffer_) {
buffer_->EndEvent(event_handle_);
}
}
private:
ProfileBuffer* buffer_;
int32_t event_handle_;
};
class ScopedOperatorProfile {
public:
// Adds a profile event to profile that begins with the construction
// of object and ends when the object goes out of scope.
// The lifetime of tag should be at least the lifetime of profiler.
ScopedOperatorProfile(Profiler* profiler, const char* tag, int node_index)
: buffer_(nullptr), event_handle_(0) {
if (profiler) {
buffer_ = profiler->GetProfileBuffer();
event_handle_ = buffer_->BeginEvent(
tag, ProfileEvent::EventType::OPERATOR_INVOKE_EVENT, node_index);
}
}
~ScopedOperatorProfile() {
if (buffer_) {
buffer_->EndEvent(event_handle_);
}
}
private:
ProfileBuffer* buffer_;
int32_t event_handle_;
};
} // namespace profiling
} // namespace tflite
#define VARNAME_UNIQ(name, ctr) name##ctr
#define SCOPED_OPERATOR_PROFILE(profiler, node_index) \
tflite::profiling::ScopedOperatorProfile VARNAME_UNIQ( \
_profile_, __COUNTER__)((profiler), "OpInvoke", (node_index))
#else
namespace tflite {
namespace profiling {
// A noop version of profiler when profiling is disabled.
class Profiler {
public:
Profiler() {}
void StartProfiling() {}
void StopProfiling() {}
void Reset() {}
std::vector<const ProfileEvent*> GetProfileEvents() { return {}; }
};
} // namespace profiling
} // namespace tflite
#define SCOPED_OPERATOR_PROFILE(profiler, node_index)
#endif // TFLITE_PROFILING_ENABLED
#endif // TENSORFLOW_CONTRIB_LITE_PROFILING_PROFILER_H_