| /* 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_CORE_PLATFORM_PROFILE_UTILS_CLOCK_CYCLE_PROFILER_H_ |
| #define TENSORFLOW_CORE_PLATFORM_PROFILE_UTILS_CLOCK_CYCLE_PROFILER_H_ |
| |
| #include <algorithm> |
| |
| #include "tensorflow/core/platform/logging.h" |
| #include "tensorflow/core/platform/macros.h" |
| #include "tensorflow/core/platform/profile_utils/cpu_utils.h" |
| |
| namespace tensorflow { |
| |
| class ClockCycleProfiler { |
| public: |
| ClockCycleProfiler() = default; |
| |
| // Start counting clock cycle. |
| inline void Start() { |
| CHECK(!IsStarted()) << "Profiler has been already started."; |
| start_clock_ = GetCurrentClockCycleInternal(); |
| } |
| |
| // Stop counting clock cycle. |
| inline void Stop() { |
| CHECK(IsStarted()) << "Profiler is not started yet."; |
| AccumulateClockCycle(); |
| } |
| |
| // Get how many times Start() is called. |
| inline double GetCount() { |
| CHECK(!IsStarted()); |
| return count_; |
| } |
| |
| // Get average clock cycle. |
| inline double GetAverageClockCycle() { |
| CHECK(!IsStarted()); |
| return average_clock_cycle_; |
| } |
| |
| // TODO(satok): Support more statistics (e.g. standard deviation) |
| // Get worst clock cycle. |
| inline double GetWorstClockCycle() { |
| CHECK(!IsStarted()); |
| return worst_clock_cycle_; |
| } |
| |
| // Dump statistics |
| void DumpStatistics(const string& tag); |
| |
| private: |
| inline uint64 GetCurrentClockCycleInternal() { |
| const uint64 clockCycle = profile_utils::CpuUtils::GetCurrentClockCycle(); |
| if (clockCycle <= 0) { |
| if (valid_) { |
| LOG(WARNING) << "GetCurrentClockCycle is not implemented." |
| << " Return 1 instead."; |
| valid_ = false; |
| } |
| return 1; |
| } else { |
| return clockCycle; |
| } |
| } |
| |
| inline bool IsStarted() const { return start_clock_ > 0; } |
| |
| inline void AccumulateClockCycle() { |
| const uint64 now = GetCurrentClockCycleInternal(); |
| const double clock_diff = static_cast<double>(now - start_clock_); |
| const double next_count = count_ + 1.0; |
| const double next_count_inv = 1.0 / next_count; |
| const double next_ave_cpu_clock = |
| next_count_inv * (average_clock_cycle_ * count_ + clock_diff); |
| count_ = next_count; |
| average_clock_cycle_ = next_ave_cpu_clock; |
| worst_clock_cycle_ = std::max(worst_clock_cycle_, clock_diff); |
| start_clock_ = 0; |
| } |
| |
| uint64 start_clock_{0}; |
| double count_{0.0}; |
| double average_clock_cycle_{0.0}; |
| double worst_clock_cycle_{0.0}; |
| bool valid_{true}; |
| |
| TF_DISALLOW_COPY_AND_ASSIGN(ClockCycleProfiler); |
| }; |
| |
| } // namespace tensorflow |
| |
| #endif // TENSORFLOW_CORE_PLATFORM_PROFILE_UTILS_CLOCK_CYCLE_PROFILER_H_ |