chombo-discharge
Loading...
Searching...
No Matches
CD_TimerImplem.H
Go to the documentation of this file.
1/* chombo-discharge
2 * Copyright © 2021 SINTEF Energy Research.
3 * Please refer to Copyright.txt and LICENSE in the chombo-discharge root directory.
4 */
5
12#ifndef CD_TimerImplem_H
13#define CD_TimerImplem_H
14
15// Std includes
16#include <sstream>
17#include <iostream>
18#include <fstream>
19#include <iomanip>
20
21// Chombo includes
22#ifdef CH_MPI
23#include <SPMD.H>
24#endif
25
26// Our includes
27#include <CD_Timer.H>
28#include <CD_NamespaceHeader.H>
29
30inline Real
32{
33
34 // TLDR: This just returns the current time in seconds (since an arbitrary time in the past).
35 const auto currentTime = std::chrono::steady_clock::now();
36 const auto durationInSeconds = std::chrono::duration<Real>(currentTime.time_since_epoch());
37
38 return durationInSeconds.count();
39}
40
46
48{
49 m_events.clear();
50}
51
52inline void
54{
55 m_events.clear();
56}
57
58inline void
60{
61#ifdef _OPENMP
62 if (omp_get_thread_num() == 0) {
63#endif
64 if (m_events.find(a_event) == m_events.end()) { // Create a new event.
65 const TimePoint startTime = Clock::now();
66 const Duration elapsedTime = Duration(0.0);
67
68 m_events.emplace(a_event, std::make_tuple(false, startTime, elapsedTime));
69 }
70 else { // If the event is not new, we just leave the elapsed time intact.
71 // const TimePoint startTime = Clock::now();
74
75 if (stoppedEvent) { // Only start the event if it is not already running.
76 const TimePoint startTime = Clock::now();
78
80 }
81 }
82#ifdef _OPENMP
83 }
84#endif
85}
86
87inline void
89{
90#ifdef _OPENMP
91 if (omp_get_thread_num() == 0) {
92#endif
93 if (m_events.find(a_event) != m_events.end()) {
95
97 const TimePoint stopTime = Clock::now();
101
103 }
104 else {
105 std::cerr << "Timer::stopEvent -- event '" + a_event + "' has not been started\n";
106 }
107#ifdef _OPENMP
108 }
109#endif
110}
111
112inline void
114{
115 std::ios::fmtflags oldFlags = a_outputStream.flags();
116#ifdef _OPENMP
117 if (omp_get_thread_num() == 0) {
118#endif
120 header
121 << "| ---------------------------------------------------------------------------------------------------------|"
122 << "\n"
123 << "| " + m_processName + " kernel report: " << "\n"
124 << "| ---------------------------------------------------------------------------------------------------------|"
125 << "\n"
126 << "| " << std::left << std::setw(25) << "Event" << "| " << std::right << std::setw(8) << "Loc. (s)" << "| "
127 << std::right << std::setw(8) << "Loc. (%)"
128#ifdef CH_MPI
129 << "| " << std::right << std::setw(8) << "Min. (s)" << "| " << std::right << std::setw(8) << "Max. (s)" << "| "
130 << std::right << std::setw(8) << "Avg. (s)" << "| " << std::right << std::setw(8) << "Dev. (s)" << "| "
131 << std::right << std::setw(8) << "Min rank" << "| " << std::right << std::setw(8) << "Max rank" << "| "
132#endif
133 << "\n"
134 << "| ---------------------------------------------------------------------------------------------------------|"
135 << "\n";
136
137 a_outputStream << header.str();
138#ifdef _OPENMP
139 }
140#endif
142}
143
144inline void
146{
147 std::ios::fmtflags oldFlags = a_outputStream.flags();
148#ifdef _OPENMP
149 if (omp_get_thread_num() == 0) {
150#endif
152
153 tail
154 << "| ---------------------------------------------------------------------------------------------------------|"
155 << "\n"
156 << "| Local elapsed time = " << std::fixed << std::setprecision(4) << a_elapsedTime.first << " seconds" << "\n"
157 << "| Global elapsed time = " << std::fixed << std::setprecision(4) << a_elapsedTime.second << " seconds" << "\n"
158 << "| ---------------------------------------------------------------------------------------------------------|"
159 << "\n";
160
161 a_outputStream << tail.str();
162#ifdef _OPENMP
163 }
164#endif
166}
167
168inline void
170{
171 // This routine prints a header, the timing report for the various event, and a tail. All events are included
172 // but unfinished ones are not counted towards the elapsed time.
173 std::ios::fmtflags oldFlags = a_outputStream.flags();
174#ifdef _OPENMP
175 if (omp_get_thread_num() == 0) {
176#endif
177
178 this->printReportHeader(a_outputStream);
179
180 const std::pair<Real, Real> totalTime = this->computeTotalElapsedTime(a_localReportOnly);
181 const Real totalTimeLocal = totalTime.first;
182
183 for (const auto& e : m_events) {
184
185 const std::string& eventName = e.first;
186 const bool finishedEvent = std::get<StoppedEvent>(e.second);
187
196
197 if (finishedEvent) {
200
203
204#ifdef CH_MPI
205 if (!a_localReportOnly) {
206
207 const int srcRank = 0;
208 const int numRank = numProc();
209
212
213 // Compute average time and standard deviation
214 Real average;
215 Real sigma;
216
217 Real maxTime = std::numeric_limits<Real>::min();
218 Real minTime = std::numeric_limits<Real>::max();
219
220 int minRank;
221 int maxRank;
222
223 if (procID() == 0) {
224
225 average = 0.0;
226 for (int i = 0; i < allDurations.size(); i++) {
227 average += allDurations[i];
228
229 if (allDurations[i] < minTime) {
230 minRank = i;
232 }
233 if (allDurations[i] > maxTime) {
234 maxRank = i;
236 }
237 }
238 average *= 1. / numRank;
239
240 sigma = 0.0;
241 for (int i = 0; i < allDurations.size(); i++) {
242 sigma += sqrt(std::pow(allDurations[i] - average, 2));
243 }
244 sigma = sqrt(sigma / numRank);
245 }
246
247 broadcast(average, srcRank);
251 broadcast(minRank, srcRank);
252 broadcast(maxRank, srcRank);
253
256 ssAvgDuration << std::fixed << std::setprecision(4) << average;
258 ssMinRank << std::fixed << std::setprecision(4) << minRank;
259 ssMaxRank << std::fixed << std::setprecision(4) << maxRank;
260 }
261 else {
262 ssMinDuration << " N/A ";
263 ssMaxDuration << " N/A ";
264 ssAvgDuration << " N/A ";
265 ssDevDuration << " N/A ";
266 ssMinRank << " N/A ";
267 ssMaxRank << " N/A ";
268 }
269#endif
270 }
271 else {
272 ssLocalDuration << " - ";
273 ssPercentage << " - ";
274 ssMinDuration << " - ";
275 ssMaxDuration << " - ";
276 ssAvgDuration << " - ";
277 ssDevDuration << " - ";
278 ssMinRank << " - ";
279 ssMaxRank << " - ";
280 }
281
283
284 // Now print to pout
285 outputString << "| " << std::left << std::setw(25) << eventName << "| " << std::right << std::setw(8)
286 << ssLocalDuration.str() << "| " << std::right << std::setw(8) << ssPercentage.str()
287#ifdef CH_MPI
288 << "| " << std::right << std::setw(8) << ssMinDuration.str() << "| " << std::right << std::setw(8)
289 << ssMaxDuration.str() << "| " << std::right << std::setw(8) << ssAvgDuration.str() << "| "
290 << std::right << std::setw(8) << ssDevDuration.str() << "| " << std::right << std::setw(8)
291 << ssMinRank.str() << "| " << std::right << std::setw(8) << ssMaxRank.str()
292#endif
293 << "| " << "\n";
294
296 }
297
298 this->printReportTail(a_outputStream, totalTime);
299
300#ifdef _OPENMP
301 }
302#endif
304}
305
308{
309
312
313 for (const auto& e : m_events) {
314 const bool finishedEvent = std::get<StoppedEvent>(e.second);
315
316 if (finishedEvent) {
319
321 }
322 }
323
324#ifdef CH_MPI
325 if (!a_localReportOnly) {
327 }
328 else {
330 }
331#else
333#endif
334
336}
337
338inline void
340{
341
342 // First, go through all events and gather the times on the master rank.
344 headerRow.emplace_back("# MPI rank");
345
346 // These are all the times for the finished events. We organize this is a 2D vector which is M x numRank long. Here,
347 // finishedEvents[0] contains the elapsed times for one of the events. The length of finishedEvents[0] is exactly
348 // numRank long
350
351#if CH_MPI
352 constexpr int srcRank = 0;
353 const int numRanks = numProc();
354#else
355 const int numRanks = 1;
356#endif
357
358 for (const auto& e : m_events) {
359 const std::string& eventName = e.first;
361
363
364 // If we had an event that finished, we gather all the data on the master rank.
365 if (finishedEvent) {
366
369#ifdef CH_MPI
371#else
373#endif
374
375 finishedEvents.emplace_back(allTimes.stdVector());
376 headerRow.emplace_back(eventName);
377 }
378 }
379
380 // Open a file and start writing.
381#if CH_MPI
382 if (procID() == srcRank) {
383#endif
384#ifdef _OPENMP
385 if (omp_get_thread_num() == 0) {
386#endif
388 f.open(a_fileName, std::ios_base::trunc);
389
390 const int width = 12;
391 for (int col = 0; col < headerRow.size(); col++) {
392 f << std::left << std::setw(width) << headerRow[col] << "\t";
393 }
394 f << "\n";
395
396 // Write the data for rank = 0 etc
397 for (int irank = 0; irank < numRanks; irank++) {
398 f << std::left << std::setw(width) << irank << "\t";
399 for (int event = 0; event < finishedEvents.size(); event++) {
400 f << std::left << std::setw(width) << finishedEvents[event][irank] << "\t";
401 }
402 f << "\n";
403 }
404
405 f.close();
406#ifdef _OPENMP
407 }
408#endif
409#if CH_MPI
410 }
411#endif
412}
413
414#include <CD_NamespaceFooter.H>
415
416#endif
Implementation of CD_Timer.H.
void stopEvent(const std::string a_event) noexcept
Stop an event.
Definition CD_TimerImplem.H:88
std::chrono::duration< Real > Duration
Duration in seconds.
Definition CD_Timer.H:46
~Timer()
Destructor.
Definition CD_TimerImplem.H:47
void startEvent(const std::string a_event) noexcept
Start an event.
Definition CD_TimerImplem.H:59
std::string m_processName
Process name. Used for input/output.
Definition CD_Timer.H:135
void writeReportToFile(const std::string a_fileName) const noexcept
Print all timed events to a file.
Definition CD_TimerImplem.H:339
std::chrono::steady_clock::time_point TimePoint
Point in time.
Definition CD_Timer.H:41
void printReportHeader(std::ostream &a_outputStream) const noexcept
Print report header.
Definition CD_TimerImplem.H:113
std::map< std::string, std::tuple< bool, TimePoint, Duration > > m_events
Timer events. First entry is the name of the event.
Definition CD_Timer.H:141
Timer()=default
Default constructor. This creates a timer without any timer events and without a name.
void printReportTail(std::ostream &a_outputStream, const std::pair< Real, Real > a_elapsedTime) const noexcept
Print report tail.
Definition CD_TimerImplem.H:145
static Real wallClock()
Static function which returns the time (in seconds) between now and an arbitrary time in the past.
Definition CD_TimerImplem.H:31
std::pair< Real, Real > computeTotalElapsedTime(const bool a_localReportOnly) const noexcept
Compute the total time for all finished events.
Definition CD_TimerImplem.H:307
void clear() noexcept
Clear all events.
Definition CD_TimerImplem.H:53
void eventReport(std::ostream &a_outputStream, const bool a_localReportOnly=false) const noexcept
Print all timed events to cout.
Definition CD_TimerImplem.H:169
Base class for a tracer particle solver. This solver can advance particles in a pre-defined velocity ...
Definition CD_TracerParticleSolver.H:37
TracerParticleSolver()
Default constructor.
Definition CD_TracerParticleSolverImplem.H:25