Updated Timer class to prevent wrong measurements

Merged Daniel Lindblad requested to merge aeroacoustics/nektar:feature/compressibleTimings into master

Issue/feature addressed

The compressible flow solver uses the Timer class to check the execution time of different functions. However, the functions that were being timed were not necessarily the most expensive ones, and the output of the timings was therefore misleading. In addition to this, the timer provided by the Timer class could be stopped before it was started, or started and then never stopped, which meant that a user might accidentally collect wrong timings if, e.g., the timer was not stopped after the function that it times was finished.

Proposed solution

This merge requests provides two updates. First, the functions inside the compressible flow solver that are being timed have been revisited. We have also made use of the iolevel variable inside the Timer class to group timers into different categories based on their location inside the call hierarchy. For example, the timers that have iolevel=0 refer to high-level functions that, e.g., compute the right hand side (residual) and apply the preconditioner. These calls are then split into several lower-level functions, such as convective and diffusive flux, which are timed with a timer that has a higher iolevel. It is important to point out that the choice of iolevel for a specific function is ambiguous. In particular, a function may be called from several different places in the call stack. Therefore, the current proposed classification of timers into iolevels is only a suggestion. However, we do believe that it captures the high-level functionality of the code quite well.

The second update provided by this merge request is an update of the Timer class. In particular, the Timer class now checks that it is not running when the user calls the function that starts it (Timer::Start()). It also checks that the timer is running when the user calls the function to stop it (Timer::Stop()). Finally, there is a function which is used to add the latest timing to a static variable that holds the total time spend inside each function (Timer::AccumulateRegion(std::string region, int iolevel)). This function calls Timer::Elapsed(), which is used to compute the last time interval that was recorded by the timer. Before, it was possible to call this function while the timer was still running. This bug has been fixed now by checking that the timer was stopped before the time interval is computed. Finally, the output of the Timer classed has been updated such that the timers are written in groups based on their iolevel. The user selects how many iolevels it want to print using a session file parameter called Timer_IO_Level.


The checks related to the Timer class were implemented by adding an ASSERTL0() to Timer::Start(), Timer::End() and Timer::Elapsed(). The improved formatting of output (by grouping the output into IO levels), has been added to the Timer::PrintElapsedRegions(). Also note that the call to Timer::PrintElapsedRegions() now is enabled by specifying the Timer_IO_Level parameter in the session file to a number greater than -1. Before, the user had to use verbose mode to see the timers. This change is implemented on rows 76-79 in CompressibleFlowSolver.cpp.

The updated locations for the timers should be easily seen from the changes the merge request provide.



Please add any other information that could be useful for reviewers.


  • Functions and classes, or changes to them, are documented.
  • User guide/documentation is updated.
  • Changelog is updated.
  • Suitable tests added for new functionality.
  • Newly added files are correctly formatted.
  • License added to any new files.
  • No extraneous files have been added (e.g. compiler output or test data files).
Edited by Daniel Lindblad

Merge request reports