timer.h
Go to the documentation of this file.
1 /*
2  This file is part of the Ristra tangram project.
3  Please see the license file at the root of this repository, or at:
4  https://github.com/laristra/portage/blob/master/LICENSE
5 */
6 
7 #pragma once
8 
9 #include <chrono>
10 #include <cstdio>
11 #include <fstream>
12 
13 /* Wrapper for high precision time point */
14 namespace timer {
15 
19 inline std::chrono::high_resolution_clock::time_point now() {
21 }
22 
27 inline float elapsed(
28  std::chrono::high_resolution_clock::time_point& tic, bool reset = false
29 ) {
30  auto const toc = now();
31  auto const timing = static_cast<float>(
32  std::chrono::duration_cast<std::chrono::milliseconds>(toc - tic).count()
33  ) / 1.E3;
34 
35  if (reset) { tic = now(); }
36  return timing;
37 }
38 
43 inline void reset(
44  std::chrono::high_resolution_clock::time_point& tic, float* cumul = nullptr
45 ) {
46  if (cumul != nullptr) {
47  *cumul += elapsed(tic);
48  }
49  tic = now();
50 }
51 
52 } // namespace 'Portage::timer'
53 
54 class Profiler {
55 
56 public:
57  // time counters
58  struct {
59  float mesh_init = 0;
60  float redistrib = 0;
61  float interface = 0;
62  float search = 0;
63  float intersect = 0;
64  float gradient = 0;
65  float interpolate = 0;
66  float mismatch = 0;
67  float remap = 0;
68  float total = 0;
69  } time;
70 
71  // run parameters
72  struct {
73  int ranks = 1;
74  int threads = 1;
75  int dim = 2;
76  int nsource = 0;
77  int ntarget = 0;
78  int nmats = 0;
79  int order = 1;
80  std::string output = "";
81  } params;
82 
83  // constructors
84  Profiler() = default;
85  Profiler(Profiler const&) = delete;
86  Profiler(Profiler&&) noexcept = default;
87  ~Profiler() = default;
88 
89  // reset all counters
90  inline void reset() {
91  time.mesh_init = 0;
92  time.redistrib = 0;
93  time.interface = 0;
94  time.search = 0;
95  time.intersect = 0;
96  time.gradient = 0;
97  time.interpolate = 0;
98  time.mismatch = 0;
99  time.remap = 0;
100  time.total = 0;
101  params.ranks = 1;
102  params.threads = 1;
103  params.dim = 2;
104  params.nsource = 0;
105  params.ntarget = 0;
106  params.nmats = 0;
107  params.order = 1;
108  params.output = "";
109  }
110 
111  // dump all data to file
112  inline bool dump() {
113 
114  // save timing for each step
115  constexpr int const nsteps = 10;
116  constexpr float const time_eps = 1.E-4;
117 
118  float const elap[nsteps] = {
119  std::max(time_eps, time.mesh_init),
120  std::max(time_eps, time.redistrib),
121  std::max(time_eps, time.interface),
122  std::max(time_eps, time.search),
123  std::max(time_eps, time.intersect),
124  std::max(time_eps, time.gradient),
125  std::max(time_eps, time.interpolate),
126  std::max(time_eps, time.mismatch),
127  std::max(time_eps, time.remap),
128  std::max(time_eps, time.total - time.mesh_init - time.interface - time.remap)
129  };
130 
131  int time_ratio[nsteps];
132  int max_elap = 0;
133 
134  for (int i = 0; i < nsteps; ++i) {
135  time_ratio[i] = static_cast<int>(100 * (elap[i] / time.total));
136  max_elap = std::max(max_elap, static_cast<int>(elap[i]));
137  }
138 
139  // for number formatting
140  int const n_dec = 3;
141  int const n_tot = 1 + n_dec + (max_elap > 0 ? ((int) std::floor(std::log10(max_elap))) + 1 : 0);
142 
143  std::string const& path = params.output;
144  std::printf("\nRecap: total elapsed time %.3f s\n", time.total);
145  std::printf(" \u2022 %2d %% generate mesh \e[32m(%*.3f s)\e[0m.\n", time_ratio[0], n_tot, elap[0]);
146  std::printf(" \u2022 %2d %% redistribute \e[32m(%*.3f s)\e[0m.\n", time_ratio[1], n_tot, elap[1]);
147  std::printf(" \u2022 %2d %% interface reconst. \e[32m(%*.3f s)\e[0m.\n", time_ratio[2], n_tot, elap[2]);
148  std::printf(" \u2022 %2d %% search \e[32m(%*.3f s)\e[0m.\n", time_ratio[3], n_tot, elap[3]);
149  std::printf(" \u2022 %2d %% intersect \e[32m(%*.3f s)\e[0m.\n", time_ratio[4], n_tot, elap[4]);
150  std::printf(" \u2022 %2d %% gradient \e[32m(%*.3f s)\e[0m.\n", time_ratio[5], n_tot, elap[5]);
151  std::printf(" \u2022 %2d %% interpolate \e[32m(%*.3f s)\e[0m.\n", time_ratio[6], n_tot, elap[6]);
152  std::printf(" \u2022 %2d %% mismatch \e[32m(%*.3f s)\e[0m.\n", time_ratio[7], n_tot, elap[7]);
153  std::printf(" \u2022 %2d %% remap \e[32m(%*.3f s)\e[0m.\n", time_ratio[8], n_tot, elap[8]);
154  std::printf(" \u2022 %2d %% post-process \e[32m(%*.3f s)\e[0m.\n", time_ratio[9], n_tot, elap[9]);
155  std::fflush(stdout);
156 
157  std::printf("Exporting stats to '%s' ... ", path.data());
158  std::fflush(stdout);
159 
160  auto tic = timer::now();
161 
162  std::ofstream file(path, std::ios::out|std::ios::app);
163  if (not file.good()) {
164  std::fprintf(stderr, "Could not open file :%s\n", path.data());
165  return false;
166  }
167 
168  // add header if file is empty
169  std::ifstream checkfile(path);
170  assert(checkfile.good());
171  checkfile.seekg(0, std::ios::end);
172  bool const is_empty = checkfile.tellg() == 0;
173  checkfile.close();
174 
175  // generate headers if required
176  if (is_empty) {
177  file << "# Profiling data for t-junction app" << std::endl;
178  file << "#" << std::endl;
179  file << "# Fields" << std::endl;
180  file << "# 1. number of ranks" << std::endl;
181  file << "# 2. number of threads" << std::endl;
182  file << "# 3. initialization time" << std::endl;
183  file << "# 4. redistribution time" << std::endl;
184  file << "# 5. interface reconstruction time" << std::endl;
185  file << "# 6. search time" << std::endl;
186  file << "# 7. intersection time" << std::endl;
187  file << "# 8. gradient time" << std::endl;
188  file << "# 9. interpolation time" << std::endl;
189  file << "# 10. mismatch time" << std::endl;
190  file << "# 11. remapping time" << std::endl;
191  file << "# 12. total elapsed time" << std::endl;
192  file << "# 13. mesh dimension" << std::endl;
193  file << "# 14. source cells count" << std::endl;
194  file << "# 15. target cells count" << std::endl;
195  file << "# 16. materials count" << std::endl;
196  file << "# 17. remap order" << std::endl << std::endl;
197  }
198 
199  file << params.ranks << "\t"
200  << params.threads << "\t"
201  << time.mesh_init << "\t"
202  << time.redistrib << "\t"
203  << time.interface << "\t"
204  << time.search << "\t"
205  << time.intersect << "\t"
206  << time.gradient << "\t"
207  << time.interpolate << "\t"
208  << time.gradient << "\t"
209  << time.remap << "\t"
210  << time.total << "\t"
211  << params.dim << "\t"
212  << params.nsource << "\t"
213  << params.ntarget << "\t"
214  << params.nmats << "\t"
215  << params.order << std::endl;
216 
217  file.close();
218  std::printf("done. \e[32m(%.3f s)\e[0m\n", timer::elapsed(tic));
219  std::fflush(stdout);
220  return true;
221  }
222 };
std::chrono::high_resolution_clock::time_point now()
Get current time.
Definition: timer.h:19
Definition: timer.h:14
float elapsed(std::chrono::high_resolution_clock::time_point &tic, bool reset=false)
Get elapsed time in seconds.
Definition: timer.h:27
bool dump()
Definition: timer.h:112
void reset(std::chrono::high_resolution_clock::time_point &tic, float *cumul=nullptr)
Dump current time and reset it afterwards.
Definition: timer.h:43
Definition: timer.h:54