MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
dlbtimer.h
Go to the documentation of this file.
1// Copyright (C) 2024 The m-AIA AUTHORS
2//
3// This file is part of m-AIA (https://git.rwth-aachen.de/aia/m-AIA/m-AIA)
4//
5// SPDX-License-Identifier: LGPL-3.0-only
6
7#ifndef DLBTIMER_H
8#define DLBTIMER_H
9
10#include <iomanip>
11#include <sys/times.h>
12#include <unistd.h>
13#include "INCLUDE/maiatypes.h"
14#include "IO/infoout.h"
15#include "UTIL/timer.h"
16#include "functions.h"
17#include "globalvariables.h"
18
19// Note: required for writing to m_log, since dlbtimer.h is itself included in
20// globalvariables.h
21#ifndef PVPLUGIN
22extern InfoOutFile m_log;
24#else
25extern std::ostream& m_log;
26extern std::ostream& maia_res;
27#endif
28
29namespace maia {
30namespace dlbTimer {
31
32class DlbTimer {
33 private:
35 const MInt m_dlbTimerId = -1;
36
40
44 MFloat m_timerWallTime[2] = {0.0, 0.0}; // wall time
45 MFloat m_timerUserTime[2] = {0.0, 0.0}; // process user time
47 MFloat m_recordedWallTime[2] = {0.0, 0.0};
48 MFloat m_recordedUserTime[2] = {0.0, 0.0};
50 MBool m_timerRunning[2] = {false, false};
51
52 public:
54 DlbTimer(const MInt timerId) : m_dlbTimerId(timerId) {}
55
58 inline void enableDlbTimers() {
60 TERMM(1, "Error: load balancing timers already enabled.");
61 }
62 m_dlbTimersEnabled = true;
63
64 // Reset timer status
65 for(MBool& i : m_timerRunning) {
66 i = false;
67 }
68 }
69
71 inline void disableDlbTimers() {
73 TERMM(1, "Error: load balancing timers not enabled.");
74 }
75 m_dlbTimersEnabled = false;
76 }
77
78 inline void reEnableDlbTimer() {
80 TERMM(1, "Error: load balancing timers already enabled.");
81 }
82 m_dlbTimersEnabled = true;
83 }
84
86 inline MBool dlbTimersEnabled() const { return m_dlbTimersEnabled; }
87
89
91 inline void startLoadTimer(const MString& name) {
93 return;
94 }
96 TERMM(1, name + "; Error: cannot start load timer while idle timer still running.");
97 }
99 }
100
102 inline void stopLoadTimer(const MString& name) {
103 if(!m_dlbTimersEnabled) {
104 return;
105 }
107 }
108
111
113 inline MFloat returnLoadRecord(const MInt mode = 0) const {
114#ifdef MAIA_DEBUG_DLB_TIMER
116 m_log << "DLB timer #" << m_dlbTimerId << " "
117 << " returnLoadRecord: " << m_recordedWallTime[m_loadTimerId] << " user " << m_recordedUserTime[m_loadTimerId]
118 << " diff " << diff << std::endl;
119#endif
121 }
122
124 inline void startIdleTimer(const MString& name) {
125 if(!m_dlbTimersEnabled) {
126 return;
127 }
129 TERMM(1, name + "; Error: cannot start idle timer while load timer still running.");
130 }
132 }
133
135 inline void stopIdleTimer(const MString& name) {
136 if(!m_dlbTimersEnabled) {
137 return;
138 }
140 }
141
144
146 inline MFloat returnIdleRecord(const MInt mode = 0) const {
147#ifdef MAIA_DEBUG_DLB_TIMER
149 m_log << "DLB timer #" << m_dlbTimerId << " "
150 << " returnIdleRecord: " << m_recordedWallTime[m_idleTimerId] << " user " << m_recordedUserTime[m_idleTimerId]
151 << " diff " << diff << std::endl;
152#endif
154 }
155
156 static MInt noTimers() {
157 return 2; // Default: load and idle timer
158 }
159
160 private:
161 // General DLB timer methods
162
164 void startSolverTimer(const MInt timerId, const MString& name) {
165 if(m_timerRunning[timerId]) {
166 TERMM(1, name + "; error in startSolverTimer(" + std::to_string(timerId) + "): timer already running, dlbTimerId "
167 + std::to_string(m_dlbTimerId));
168 } else {
169 m_timerWallTime[timerId] = MPI_Wtime();
170 m_timerUserTime[timerId] = cpuTime();
171
172 m_timerRunning[timerId] = true;
173#ifdef MAIA_DEBUG_DLB_TIMER
174 m_log << "DLB timer #" << m_dlbTimerId << " startSolverTimer #" << timerId << " at time "
175 << m_timerWallTime[timerId] << " from " << name << std::endl;
176#endif
177 }
178 }
179
181 void stopSolverTimer(const MInt timerId, const MString& name) {
182 if(!m_timerRunning[timerId]) {
183 TERMM(1, name + "; error in stopSolverTimer(" + std::to_string(timerId) + "): timer not running, dlbTimerId "
184 + std::to_string(m_dlbTimerId) + " DLB status is " + std::to_string(dlbTimersEnabled()));
185 } else {
186 const MFloat t_stop = MPI_Wtime();
187 const MFloat t_diff = t_stop - m_timerWallTime[timerId];
188 m_recordedWallTime[timerId] += t_diff;
189
190 const MFloat t_user = cpuTime();
191 const MFloat t_user_diff = t_user - m_timerUserTime[timerId];
192 m_recordedUserTime[timerId] += t_user_diff;
193
194 m_timerRunning[timerId] = false;
195#ifdef MAIA_DEBUG_DLB_TIMER
196 m_log << "DLB timer #" << m_dlbTimerId << " stopSolverTimer #" << timerId << " at time "
197 << m_timerWallTime[timerId] << " with t_diff " << t_diff << " user time diff " << t_user_diff << " from "
198 << name << std::endl;
199#endif
200 }
201 }
202
204 void resetSolverTimer(const MInt timerId) {
205 if(m_timerRunning[timerId]) {
206 TERMM(1, "error in resetSolverTimer(" + std::to_string(timerId) + "): timer still running, dlbTimerId "
207 + std::to_string(m_dlbTimerId));
208 } else {
209 m_recordedWallTime[timerId] = 0.0;
210 m_recordedUserTime[timerId] = 0.0;
211#ifdef MAIA_DEBUG_DLB_TIMER
212 m_log << "DLB timer #" << m_dlbTimerId << " resetSolverTimer #" << timerId << std::endl;
213#endif
214 }
215 }
216};
217
218} // namespace dlbTimer
219} // namespace maia
220
221
224#define ENSURE_VALID_TIMERID(timerId, at) \
225 do { \
226 ASSERT(timerId >= 0 && timerId < noDlbTimers(), "invalid dlbTimerId: " + std::to_string(timerId)); \
227 } while(false)
228#define ENSURE_VALID_TIMERMODE(mode, at) \
229 do { \
230 ASSERT(mode >= 0 && mode <= 1, "invalid timer mode: " + std::to_string(mode)); \
231 } while(false)
232
233 public:
235 void createDlbTimers(const MInt noTimers, const MBool ignore = false) {
236 if(noDlbTimers() > 0) {
237 TERMM(1, "createDlbTimers should only be called once!");
238 }
239
240 // High-resolution per-process CPU timer
241 timespec tp;
242 clock_getres(CLOCK_PROCESS_CPUTIME_ID, &tp);
243 m_log << "DLB timer: CLOCK PROCESS CPUTIME RESOLUTION " << tp.tv_sec << "s " << tp.tv_nsec << "nsec" << std::endl;
244
245 for(MInt i = 0; i < noTimers; i++) {
246 const MInt newTimerId = m_dlbTimers.size();
247 m_dlbTimers.emplace_back(newTimerId);
248 }
249
250 m_ignoreDlbTimers = ignore;
251 }
252
254 void enableDlbTimers(const MInt dlbTimerId) {
256 return;
257 }
258
259 ENSURE_VALID_TIMERID(dlbTimerId, AT_);
260 m_dlbTimers[dlbTimerId].enableDlbTimers();
261 m_enabled = true; // At least this one timer is enabled
262 }
263
265 void enableAllDlbTimers(const MBool* const wasEnabled = nullptr) {
267 return;
268 }
269
270 for(MInt i = 0; i < noDlbTimers(); i++) {
271 // Check if a status array is given and restore previous state
272 MBool enableTimers = true;
273 if(wasEnabled != nullptr) {
274 enableTimers = wasEnabled[i];
275 }
276
277 if(enableTimers) {
279 }
280 }
281 }
282
284 void disableDlbTimers(const MInt dlbTimerId) {
286 return;
287 }
288
289 ENSURE_VALID_TIMERID(dlbTimerId, AT_);
290 m_dlbTimers[dlbTimerId].disableDlbTimers();
291
292 MBool anyEnabled = false;
293 for(MInt i = 0; i < noDlbTimers(); i++) {
294 anyEnabled |= m_dlbTimers[dlbTimerId].dlbTimersEnabled();
295 }
296 m_enabled = anyEnabled;
297 }
298
300 void disableAllDlbTimers(MBool* const wasEnabled = nullptr) {
302 return;
303 }
304
305 if(m_runningTimerId != -1) {
306 TERMM(1, "Cannot disable all DLB timers, timer " + std::to_string(m_runningTimerId) + " still running.");
307 }
308 for(MInt i = 0; i < noDlbTimers(); i++) {
309 const MBool timersEnabled = dlbTimersEnabled(i);
310
311 // Store current timer status if requested (pointer != nullptr passed to function)
312 if(wasEnabled != nullptr) {
313 wasEnabled[i] = timersEnabled;
314 }
315
316 if(timersEnabled) {
318 }
319 }
320 m_enabled = false; // All timers are disabled
321 }
322
324 MBool dlbTimersEnabled(const MInt dlbTimerId) {
326 return false;
327 }
328
329 ENSURE_VALID_TIMERID(dlbTimerId, AT_);
330 return m_dlbTimers[dlbTimerId].dlbTimersEnabled();
331 }
332
334 void startLoadTimer(const MInt dlbTimerId, const MString& name) {
336 return;
337 }
338 ENSURE_VALID_TIMERID(dlbTimerId, name);
339
340 if(!dlbTimersEnabled(dlbTimerId)) {
341 return;
342 }
343
344 // Check that no load/idle timer is currently running
345 if(m_runningTimerId != -1) {
346 TERMM(1, "Cannot start load timer " + std::to_string(dlbTimerId) + ", timer " + std::to_string(m_runningTimerId)
347 + " already running.");
348 }
349
350 m_dlbTimers[dlbTimerId].startLoadTimer(name);
351 m_runningTimerId = dlbTimerId;
352 }
353
355 void stopLoadTimer(const MInt dlbTimerId, const MString& name) {
357 return;
358 }
359 ENSURE_VALID_TIMERID(dlbTimerId, name);
360
361 if(!dlbTimersEnabled(dlbTimerId)) {
362 return;
363 }
364
365 ASSERT(dlbTimerId == m_runningTimerId, "timer id does not match the running timer id");
366 m_dlbTimers[dlbTimerId].stopLoadTimer(name);
367 m_runningTimerId = -1;
368 }
369
371 void startIdleTimer(const MInt dlbTimerId, const MString& name) {
373 return;
374 }
375 ENSURE_VALID_TIMERID(dlbTimerId, name);
376
377 if(!dlbTimersEnabled(dlbTimerId)) {
378 return;
379 }
380
381 // Check that no load/idle timer is currently running
382 if(m_runningTimerId != -1) {
383 TERMM(1, "Cannot start idle timer " + std::to_string(dlbTimerId) + ", timer " + std::to_string(m_runningTimerId)
384 + " already running.");
385 }
386
387 m_dlbTimers[dlbTimerId].startIdleTimer(name);
388 m_runningTimerId = dlbTimerId;
389 }
390
392 void stopIdleTimer(const MInt dlbTimerId, const MString& name) {
394 return;
395 }
396 ENSURE_VALID_TIMERID(dlbTimerId, name);
397
398 if(!dlbTimersEnabled(dlbTimerId)) {
399 return;
400 }
401
402 ASSERT(dlbTimerId == m_runningTimerId, "timer id does not match the running timer id");
403 m_dlbTimers[dlbTimerId].stopIdleTimer(name);
404 m_runningTimerId = -1;
405 }
406
408 void stopLoadStartIdleTimer(const MString& name) {
409 if(!m_enabled) {
410 return; // If no timer is enabled there is nothing to do
411 }
412
413 if(m_runningTimerId < 0) {
414 TERMM(1, "Cannot stop load and start idle timer, the running timer is: " + std::to_string(m_runningTimerId) + '/'
415 + name);
416 }
417 const MInt timerId = m_runningTimerId; // m_runningTimerId is reset in stopLoadTimer()
418 stopLoadTimer(timerId, name);
419 startIdleTimer(timerId, name);
420 }
421
423 void stopIdleStartLoadTimer(const MString& name) {
424 if(!m_enabled) {
425 return; // If no timer is enabled there is nothing to do
426 }
427
428 if(m_runningTimerId < 0) {
429 TERMM(1, "Cannot stop idle and start load timer, the running timer is: " + std::to_string(m_runningTimerId));
430 }
431 const MInt timerId = m_runningTimerId; // m_runningTimerId is reset in stopIdleTimer()
432 stopIdleTimer(timerId, name);
433 startLoadTimer(timerId, name);
434 }
435
437 MBool isTimerRunning() const { return (m_runningTimerId != -1); }
438
440
441 MBool isLoadTimerRunning(const MInt dlbTimerId) {
442 return m_dlbTimers[dlbTimerId].isLoadTimerRunning() && m_runningTimerId == dlbTimerId;
443 }
444
445 void reEnableDlbTimer(const MInt dlbTimerId) { m_dlbTimers[dlbTimerId].reEnableDlbTimer(); }
446
448 void checkIOTimerStatus(const MString& name) const {
449 TERMM_IF_COND(m_enabled || isTimerRunning(), "Timers still enabled and/or timer running " + name);
450 }
451
455 return;
456 }
457 for(MInt i = 0; i < noDlbTimers(); i++) {
458 m_dlbTimers[i].resetLoadRecord();
459 m_dlbTimers[i].resetIdleRecord();
460 }
461 }
462
464 inline MFloat returnLoadRecord(const MInt dlbTimerId, const MInt mode = 0) {
466 return -1.0;
467 }
468 ENSURE_VALID_TIMERID(dlbTimerId, name);
469 ENSURE_VALID_TIMERMODE(mode, name);
470 return m_dlbTimers[dlbTimerId].returnLoadRecord(mode);
471 }
472
474 inline MFloat returnIdleRecord(const MInt dlbTimerId, const MInt mode = 0) {
476 return -1.0;
477 }
478 ENSURE_VALID_TIMERID(dlbTimerId, name);
479 ENSURE_VALID_TIMERMODE(mode, name);
480 return m_dlbTimers[dlbTimerId].returnIdleRecord(mode);
481 }
482
484 MInt noDlbTimers() const { return m_dlbTimers.size(); }
485
488
489 private:
491 std::vector<maia::dlbTimer::DlbTimer> m_dlbTimers{};
498};
499
500#endif // DLBTIMER_H
Controller class for all DLB timers.
Definition: dlbtimer.h:223
void stopIdleTimer(const MInt dlbTimerId, const MString &name)
Stop the idle timer for the given DLB timer id.
Definition: dlbtimer.h:392
MInt noDlbTimers() const
Return the number of DLB timers.
Definition: dlbtimer.h:484
void startIdleTimer(const MInt dlbTimerId, const MString &name)
Start the idle timer for the given DLB timer id.
Definition: dlbtimer.h:371
void startLoadTimer(const MInt dlbTimerId, const MString &name)
Start the load timer for the given DLB timer id.
Definition: dlbtimer.h:334
void createDlbTimers(const MInt noTimers, const MBool ignore=false)
Create the given number of DLB timers.
Definition: dlbtimer.h:235
MInt noSubTimers() const
Return the number of (sub-)timers for each DLB timer.
Definition: dlbtimer.h:487
MInt m_runningTimerId
Id of the currently running DLB load/idle timer.
Definition: dlbtimer.h:493
MFloat returnLoadRecord(const MInt dlbTimerId, const MInt mode=0)
Return the load record of a DLB timer.
Definition: dlbtimer.h:464
void stopLoadTimer(const MInt dlbTimerId, const MString &name)
Stop the load timer for the given DLB timer id.
Definition: dlbtimer.h:355
void stopIdleStartLoadTimer(const MString &name)
Stop the currently running idle timer and start the corresponding load timer.
Definition: dlbtimer.h:423
MBool m_enabled
Current status of all timers; false: all timers disabled; true: at least one timer enabled.
Definition: dlbtimer.h:495
void enableDlbTimers(const MInt dlbTimerId)
Enable the given DLB timer.
Definition: dlbtimer.h:254
void reEnableDlbTimer(const MInt dlbTimerId)
Definition: dlbtimer.h:445
MBool isTimerRunning() const
Return if a timer is running.
Definition: dlbtimer.h:437
MInt whichTimerIsRunning() const
Definition: dlbtimer.h:439
void disableDlbTimers(const MInt dlbTimerId)
Disable the given DLB timer.
Definition: dlbtimer.h:284
void checkIOTimerStatus(const MString &name) const
Check the timer status during IO (no timer running and timers not enabled)
Definition: dlbtimer.h:448
void enableAllDlbTimers(const MBool *const wasEnabled=nullptr)
Enable all DLB timers (or those given by the array wasEnabled)
Definition: dlbtimer.h:265
MBool m_ignoreDlbTimers
Global switch in createDlbTimers() to ignore all DLB timers, i.e. they cannot be enabled.
Definition: dlbtimer.h:497
void resetRecords()
Reset the records of all DLB timers.
Definition: dlbtimer.h:453
MFloat returnIdleRecord(const MInt dlbTimerId, const MInt mode=0)
Return the idle record of a DLB timer.
Definition: dlbtimer.h:474
MBool dlbTimersEnabled(const MInt dlbTimerId)
Return if the given DLB timer is enabled.
Definition: dlbtimer.h:324
void stopLoadStartIdleTimer(const MString &name)
Stop the currently running load timer and start the corresponding idle timer.
Definition: dlbtimer.h:408
void disableAllDlbTimers(MBool *const wasEnabled=nullptr)
Disable all (enabled) DLB timers.
Definition: dlbtimer.h:300
MBool isLoadTimerRunning(const MInt dlbTimerId)
Definition: dlbtimer.h:441
std::vector< maia::dlbTimer::DlbTimer > m_dlbTimers
Storage of DLB timers for all solvers/couplers/...
Definition: dlbtimer.h:491
Class to create a create an output stream for a writable file, using either MPI I/O or a physical fil...
Definition: infoout.h:217
DlbTimer(const MInt timerId)
Constructor, just set the timer id.
Definition: dlbtimer.h:54
void resetIdleRecord()
Reset the idle record.
Definition: dlbtimer.h:143
MFloat returnIdleRecord(const MInt mode=0) const
Return the idle record.
Definition: dlbtimer.h:146
const MInt m_dlbTimerId
Unique DLB timer id among all DLB timers.
Definition: dlbtimer.h:35
void startLoadTimer(const MString &name)
Start the load timer.
Definition: dlbtimer.h:91
const MInt m_idleTimerId
Definition: dlbtimer.h:39
MFloat m_timerUserTime[2]
Definition: dlbtimer.h:45
MFloat m_timerWallTime[2]
Current time when the timers were started.
Definition: dlbtimer.h:44
void disableDlbTimers()
Temporarily disable timers, e.g. during adaptation.
Definition: dlbtimer.h:71
static MInt noTimers()
Definition: dlbtimer.h:156
MFloat returnLoadRecord(const MInt mode=0) const
Return the load record.
Definition: dlbtimer.h:113
void stopSolverTimer(const MInt timerId, const MString &name)
Stop the timer with the given id.
Definition: dlbtimer.h:181
void startIdleTimer(const MString &name)
Start the idle timer.
Definition: dlbtimer.h:124
MFloat m_recordedWallTime[2]
Recorded time of the timers.
Definition: dlbtimer.h:47
void resetSolverTimer(const MInt timerId)
Reset the timer with the given id.
Definition: dlbtimer.h:204
void stopIdleTimer(const MString &name)
Stop the idle timer.
Definition: dlbtimer.h:135
MBool m_timerRunning[2]
Status of the timers.
Definition: dlbtimer.h:50
const MInt m_loadTimerId
Timer indices.
Definition: dlbtimer.h:38
void stopLoadTimer(const MString &name)
Stop the load timer.
Definition: dlbtimer.h:102
MBool dlbTimersEnabled() const
Return if timers are enabled.
Definition: dlbtimer.h:86
MFloat m_recordedUserTime[2]
Definition: dlbtimer.h:48
void startSolverTimer(const MInt timerId, const MString &name)
Start the timer with the given id.
Definition: dlbtimer.h:164
MBool m_dlbTimersEnabled
Stores if the timers are enabled.
Definition: dlbtimer.h:42
void resetLoadRecord()
Reset the load record.
Definition: dlbtimer.h:110
MBool isLoadTimerRunning() const
Definition: dlbtimer.h:88
InfoOutFile m_log
Definition: dlbtimer.h:25
InfoOutFile maia_res
Definition: dlbtimer.h:26
MFloat cpuTime()
Return the process cpu time (user time) (high-resolution timer - do not use clock())
Definition: functions.h:73
InfoOutFile m_log
int32_t MInt
Definition: maiatypes.h:62
std::basic_string< char > MString
Definition: maiatypes.h:55
double MFloat
Definition: maiatypes.h:52
bool MBool
Definition: maiatypes.h:58
Namespace for auxiliary functions/classes.