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