OmniSciDB  a5dc49c757
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CpuTimer.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2023 HEAVY.AI, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #ifndef __CUDACC__
20 
21 #include <assert.h>
22 #include <chrono>
23 #include <iomanip>
24 #include <iostream>
25 #include <memory>
26 #include <string>
27 #include <unordered_map>
28 #include <vector>
29 
30 class CpuTimer {
31  using time_point = std::chrono::time_point<std::chrono::high_resolution_clock>;
32 
33  public:
35 
36  CpuTimer(const std::string& label) : timer_label_(label), nest_level_(0) {
37  initialize();
38  }
39  CpuTimer(const std::string& label, const int64_t nest_level)
40  : timer_label_(label), nest_level_(nest_level) {
41  initialize();
42  }
43 
45  if (nest_level_ == 0) {
46  print_timings();
47  }
48  }
49 
50  void start_event_timer(const std::string& event_label) {
51  start_event_timer_impl(event_label, false);
52  }
53 
54  std::shared_ptr<CpuTimer> start_nested_event_timer(const std::string& event_label) {
55  auto& event_timer = start_event_timer_impl(event_label, true);
56  return event_timer.nested_event_timer;
57  }
58 
59  void end_event_timer() {
60  if (!event_timers_.empty()) {
61  event_timers_.back().finalize();
62  }
63  }
64 
65  private:
66  struct EventTimer {
67  std::string event_label;
70  std::shared_ptr<CpuTimer> nested_event_timer{nullptr};
71  bool is_finished{false};
72 
73  EventTimer(const std::string& event_label,
74  const size_t nest_level,
75  const bool make_nested)
76  : event_label(event_label)
77  , start_time(std::chrono::high_resolution_clock::now()) {
78  if (make_nested) {
79  const std::string nested_event_label{event_label + " sub-steps"};
81  std::make_shared<CpuTimer>(nested_event_label, nest_level + 1);
82  }
83  }
84 
86  if (!is_finished) {
87  if (nested_event_timer != nullptr) {
88  nested_event_timer->finalize();
89  }
90  end_time = std::chrono::high_resolution_clock::now();
91  is_finished = true;
92  }
93  return end_time;
94  }
95  };
96 
97  EventTimer& start_event_timer_impl(const std::string& event_label,
98  const bool make_nested) {
99  if (!event_timers_.empty()) {
100  event_timers_.back().finalize();
101  }
102  event_timers_.emplace_back(EventTimer(event_label, nest_level_, make_nested));
103  return event_timers_.back();
104  }
105 
106  void initialize() { timers_start_ = std::chrono::high_resolution_clock::now(); }
107 
108  void finalize() {
109  timers_end_ = std::chrono::high_resolution_clock::now();
110  if (!event_timers_.empty()) {
111  event_timers_.back().finalize();
112  }
113  }
114 
115  void print_timings() {
116  if (nest_level_ == 0) {
117  finalize();
118  }
119  const std::string header{timer_label_ + " Timings"};
120  const std::string header_underline{std::string(header.size(), '=')};
121  const std::string nest_spaces{std::string(nest_level_ * 2, ' ')};
122  std::cout << std::endl
123  << nest_spaces << header << std::endl
124  << nest_spaces << header_underline << std::endl;
125 
126  const size_t timings_left_margin{50};
127 
128  for (auto& event_timer : event_timers_) {
129  const int64_t ms_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
130  event_timer.end_time - event_timer.start_time)
131  .count();
132  const int64_t total_ms_elapsed =
133  std::chrono::duration_cast<std::chrono::milliseconds>(event_timer.end_time -
135  .count();
136  const size_t label_width{event_timer.event_label.size()};
137  const size_t margin_calc{
138  label_width < timings_left_margin ? timings_left_margin - label_width : 0};
139 
140  std::cout << nest_spaces << event_timer.event_label << ": "
141  << std::setw(margin_calc) << std::fixed << std::setprecision(4)
142  << ms_elapsed << " ms elapsed, " << total_ms_elapsed << " ms total"
143  << std::endl;
144 
145  if (event_timer.nested_event_timer != nullptr) {
146  event_timer.nested_event_timer->print_timings();
147  std::cout << std::endl;
148  }
149  }
150  const int64_t total_ms_elapsed =
151  std::chrono::duration_cast<std::chrono::milliseconds>(timers_end_ - timers_start_)
152  .count();
153  std::cout << nest_spaces << timer_label_ << " total elapsed: " << std::fixed
154  << std::setprecision(4) << total_ms_elapsed << " ms" << std::endl;
155  }
156 
157  const std::string timer_label_;
158  const size_t nest_level_;
161  std::vector<EventTimer> event_timers_;
162 };
163 
164 #endif // #ifndef __CUDACC__
const std::string timer_label_
Definition: CpuTimer.hpp:157
std::shared_ptr< CpuTimer > start_nested_event_timer(const std::string &event_label)
Definition: CpuTimer.hpp:54
time_point timers_start_
Definition: CpuTimer.hpp:159
EventTimer & start_event_timer_impl(const std::string &event_label, const bool make_nested)
Definition: CpuTimer.hpp:97
~CpuTimer()
Definition: CpuTimer.hpp:44
const size_t nest_level_
Definition: CpuTimer.hpp:158
std::shared_ptr< CpuTimer > nested_event_timer
Definition: CpuTimer.hpp:70
void print_timings()
Definition: CpuTimer.hpp:115
void finalize()
Definition: CpuTimer.hpp:108
time_point timers_end_
Definition: CpuTimer.hpp:160
void start_event_timer(const std::string &event_label)
Definition: CpuTimer.hpp:50
TimerResolution
Definition: CpuTimer.hpp:34
EventTimer(const std::string &event_label, const size_t nest_level, const bool make_nested)
Definition: CpuTimer.hpp:73
CpuTimer(const std::string &label)
Definition: CpuTimer.hpp:36
void end_event_timer()
Definition: CpuTimer.hpp:59
void initialize()
Definition: CpuTimer.hpp:106
std::string event_label
Definition: CpuTimer.hpp:67
std::vector< EventTimer > event_timers_
Definition: CpuTimer.hpp:161
time_point end_time
Definition: CpuTimer.hpp:69
time_point start_time
Definition: CpuTimer.hpp:68
list header
Definition: report.py:113
time_point finalize()
Definition: CpuTimer.hpp:85
CpuTimer(const std::string &label, const int64_t nest_level)
Definition: CpuTimer.hpp:39
std::chrono::time_point< std::chrono::high_resolution_clock > time_point
Definition: CpuTimer.hpp:31