hyper.deal
Loading...
Searching...
No Matches
timers.h
1// ---------------------------------------------------------------------
2//
3// Copyright (C) 2020 by the hyper.deal authors
4//
5// This file is part of the hyper.deal library.
6//
7// The hyper.deal library is free software; you can use it, redistribute
8// it, and/or modify it under the terms of the GNU Lesser General
9// Public License as published by the Free Software Foundation; either
10// version 3.0 of the License, or (at your option) any later version.
11// The full text of the license can be found in the file LICENSE.MD at
12// the top level directory of hyper.deal.
13//
14// ---------------------------------------------------------------------
15
16#ifndef HYPERDEAL_TIMERS
17#define HYPERDEAL_TIMERS
18
19#include <hyper.deal/base/config.h>
20
21#include <deal.II/base/mpi.templates.h>
22
23#include <hyper.deal/base/memory_consumption.h>
24
25#include <chrono>
26#include <fstream>
27#include <ios>
28#include <map>
29
30#ifdef LIKWID_PERFMON
31# include <likwid.h>
32#endif
33
34namespace hyperdeal
35{
36 class Timer
37 {
38 public:
39 void
40 reserve(const unsigned int max_size)
41 {
42 times.reserve(max_size);
43 }
44
45 void
46 reset()
47 {
48 counter = 0;
49 accumulated_time = 0.0;
50 }
51 void
52 start()
53 {
54 temp = std::chrono::system_clock::now();
55 }
56 void
57 stop()
58 {
59 const double dt = std::chrono::duration_cast<std::chrono::microseconds>(
60 std::chrono::system_clock::now() - temp)
61 .count();
62
63 accumulated_time += dt;
64
65 if (times.capacity() > 0)
66 times.push_back(dt);
67
68 counter++;
69 }
70
71 unsigned int
72 get_counter() const
73 {
74 return counter;
75 }
76
77 double
78 get_accumulated_time() const
79 {
80 return accumulated_time;
81 }
82
83 const std::vector<double> &
84 get_log() const
85 {
86 return times;
87 }
88
89 private:
90 unsigned int counter = 0;
91 std::chrono::time_point<std::chrono::system_clock> temp;
92 double accumulated_time = 0.0;
93 std::vector<double> times;
94 };
95
96 class Timers
97 {
98 static const unsigned int max_levels = 10;
99 static const unsigned int max_timers = 100;
100 static const unsigned int max_iterations = 1000;
101
102 public:
103 Timers(const bool log_all_calls)
104 : log_all_calls(log_all_calls)
105 {
106 path.reserve(max_levels);
107 timers.reserve(max_timers);
108
109 path.emplace_back("");
110 }
111
112 Timer &operator[](const std::string &label)
113 {
114 const std::string label_ = path.back() + label;
115
116 const auto ptr = map.find(label_);
117
118 if (ptr == map.end())
119 {
120 timers.resize(timers.size() + 1);
121 map[label_] = timers.size() - 1;
122
123 if (this->log_all_calls)
124 timers.back().reserve(max_iterations);
125 return timers.back();
126 }
127 else
128 return timers[ptr->second];
129 }
130
131 void
132 reset()
133 {
134 for (auto &timer : timers)
135 timer.reset();
136 }
137
138 void
139 enter(const std::string &label)
140 {
141 path.emplace_back(path.back() + label + ":");
142 }
143
144 void
145 leave()
146 {
147 path.resize(path.size() - 1);
148 }
149
150 template <typename StreamType>
151 void
152 print(const MPI_Comm &comm, StreamType &stream) const
153 {
154 std::vector<std::pair<std::string, std::array<double, 1>>> list;
155 std::vector<std::pair<std::string, unsigned int>> list_count;
156
157 unsigned int counter = 0;
158 unsigned int max_counter = 0;
159
160 for (const auto &time : map)
161 {
162 list.emplace_back(time.first,
163 std::array<double, 1>{
164 {timers[time.second].get_accumulated_time() /
165 1000000}});
166 list_count.emplace_back(time.first,
167 timers[time.second].get_counter());
168
169 if (time.first == "id_total")
170 max_counter = counter;
171
172 counter++;
173 }
174
175 internal::print_(
176 stream, comm, list, list_count, {"Time [sec]"}, max_counter);
177 }
178
179 void
180 print_log(const MPI_Comm &comm_global, const std::string &prefix) const
181 {
182 const auto print_statistics =
183 [&](const auto &v, std::string slabel, const unsigned int tag) {
184 const auto my_rank =
185 dealii::Utilities::MPI::this_mpi_process(comm_global);
186
187 if (my_rank == 0)
188 {
189 std::ofstream myfile;
190 myfile.open(prefix + "_" + slabel + ".stat");
191
192 for (unsigned int i = 0;
193 i < dealii::Utilities::MPI::n_mpi_processes(comm_global);
194 i++)
195 {
196 std::vector<double> recv_data;
197 if (i == 0)
198 {
199 recv_data = v;
200 }
201 else
202 {
203 // wait for any request
204 MPI_Status status;
205 auto ierr =
206 MPI_Probe(MPI_ANY_SOURCE, tag, comm_global, &status);
207 AssertThrowMPI(ierr);
208
209 // determine number of ghost faces * 2 (since we are
210 // considering pairs)
211 int len;
212 MPI_Get_count(
213 &status,
214 dealii::Utilities::MPI::mpi_type_id_for_type<double>,
215 &len);
216
217 recv_data.resize(len);
218
219 // receive data
220 MPI_Recv(
221 recv_data.data(),
222 len,
223 dealii::Utilities::MPI::mpi_type_id_for_type<double>,
224 status.MPI_SOURCE,
225 status.MPI_TAG,
226 comm_global,
227 &status);
228 }
229
230 for (const auto j : recv_data)
231 myfile << i << " " << j << std::endl;
232 }
233
234 myfile.close();
235 }
236 else
237 {
238 MPI_Send(v.data(),
239 v.size(),
240 dealii::Utilities::MPI::mpi_type_id_for_type<double>,
241 0,
242 tag,
243 comm_global);
244 }
245
246 MPI_Barrier(comm_global);
247 };
248
249
250 unsigned int tag = 110;
251 for (const auto &time : map)
252 print_statistics(timers[time.second].get_log(),
253 std::string(time.first),
254 tag++);
255 }
256
257 private:
258 // translator label -> unique id
259 std::map<std::string, unsigned int> map;
260
261 // list of timers
262 std::vector<Timer> timers;
263
264 std::vector<std::string> path;
265
266 const bool log_all_calls;
267 };
268
270 {
271 public:
273 : timer(&timer)
274 {
275#ifdef PERFORMANCE_TIMING
276 this->timer->start();
277#endif
278 }
279
280 ScopedTimerWrapper(Timers &timers, const std::string &label)
281 : ScopedTimerWrapper(&timers, label)
282 {}
283
284 ScopedTimerWrapper(Timers *timers, const std::string &label)
285 :
286#ifdef PERFORMANCE_TIMING
287 timer(timers == nullptr ? nullptr : &timers->operator[](label))
288#else
289 timer(nullptr)
290#endif
291 {
292#ifdef PERFORMANCE_TIMING
293 if (timer != nullptr)
294 timer->start();
295#endif
296 }
297
299 {
300#ifdef PERFORMANCE_TIMING
301 if (timer != nullptr)
302 timer->stop();
303#endif
304 }
305
306 Timer *timer;
307 };
308
310 {
311 public:
312 ScopedLikwidTimerWrapper(const std::string label)
313 : label(label)
314 {
315#ifdef LIKWID_PERFMON
316 LIKWID_MARKER_START(label.c_str());
317#endif
318 }
319
321 {
322#ifdef LIKWID_PERFMON
323 LIKWID_MARKER_STOP(label.c_str());
324#endif
325 }
326
327 private:
328 const std::string label;
329 };
330
331
332} // namespace hyperdeal
333
334#endif
Definition timers.h:270
Definition timers.h:37
Definition timers.h:97