LCOV - code coverage report
Current view: top level - src/Utility - IpplTimings.cpp (source / functions) Coverage Total Hit
Test: final_report.info Lines: 17.6 % 125 22
Test Date: 2025-07-18 17:15:09 Functions: 33.3 % 12 4

            Line data    Source code
       1              : //
       2              : // Class IpplTimings
       3              : //   IpplTimings - a simple singleton class which lets the user create and
       4              : //   timers that can be printed out at the end of the program.
       5              : //
       6              : //   General usage
       7              : //    1) create a timer:
       8              : //       IpplTimings::TimerRef val = IpplTimings::getTimer("timer name");
       9              : //    This will either create a new one, or return a ref to an existing one
      10              : //
      11              : //    2) start a timer:
      12              : //       IpplTimings::startTimer(val);
      13              : //    This will start the referenced timer running.  If it is already running,
      14              : //    it will not change anything.
      15              : //
      16              : //    3) stop a timer:
      17              : //       IpplTimings::stopTimer(val);
      18              : //    This will stop the timer, assuming it was running, and add in the
      19              : //    time to the accumulating time for that timer.
      20              : //
      21              : //    4) print out the results:
      22              : //       IpplTimings::print();
      23              : //
      24              : 
      25              : #include "Ippl.h"
      26              : 
      27              : #include "Utility/IpplTimings.h"
      28              : 
      29              : #include <algorithm>
      30              : #include <fstream>
      31              : #include <iostream>
      32              : 
      33              : #include "Utility/Inform.h"
      34              : #include "Utility/IpplInfo.h"
      35              : 
      36              : #ifdef IPPL_ENABLE_NSYS_PROFILER
      37              : #include "nvtx3/nvToolsExt.h"
      38              : const uint32_t colors[] = { 0xff00ff00, 0xff0000ff, 0xffffff00, 0xffff00ff, 0xff00ffff, 0xffff0000, 0xffffffff };
      39              : const int num_colors = sizeof(colors)/sizeof(uint32_t);
      40              : #define PUSH_RANGE(name,cid) { \
      41              :     int color_id = cid; \
      42              :     color_id = color_id%num_colors;\
      43              :     nvtxEventAttributes_t eventAttrib = {0}; \
      44              :     eventAttrib.version = NVTX_VERSION; \
      45              :     eventAttrib.size = NVTX_EVENT_ATTRIB_STRUCT_SIZE; \
      46              :     eventAttrib.colorType = NVTX_COLOR_ARGB; \
      47              :     eventAttrib.color = colors[color_id]; \
      48              :     eventAttrib.messageType = NVTX_MESSAGE_TYPE_ASCII; \
      49              :     eventAttrib.message.ascii = name; \
      50              :     nvtxRangePushEx(&eventAttrib); \
      51              : }
      52              : #endif
      53              : 
      54              : Timing* IpplTimings::instance = new Timing();
      55              : std::stack<Timing*> IpplTimings::stashedInstance;
      56              : 
      57           20 : Timing::Timing()
      58           20 :     : TimerList()
      59           20 :     , TimerMap() {}
      60              : 
      61            0 : Timing::~Timing() {
      62            0 :     for (TimerMap_t::iterator it = TimerMap.begin(); it != TimerMap.end(); ++it) {
      63            0 :         it->second = 0;
      64              :     }
      65            0 :     TimerMap.clear();
      66              : 
      67            0 :     TimerList.clear();
      68            0 : }
      69              : 
      70              : // create a timer, or get one that already exists
      71         1140 : Timing::TimerRef Timing::getTimer(const char* nm) {
      72         1140 :     std::string s(nm);
      73         1140 :     TimerInfo* tptr          = 0;
      74         1140 :     TimerMap_t::iterator loc = TimerMap.find(s);
      75         1140 :     if (loc == TimerMap.end()) {
      76          122 :         tptr       = new TimerInfo;
      77          122 :         tptr->indx = TimerList.size();
      78          122 :         tptr->name = s;
      79          122 :         TimerMap.insert(TimerMap_t::value_type(s, tptr));
      80          122 :         TimerList.push_back(my_auto_ptr<TimerInfo>(tptr));
      81              :     } else {
      82         1018 :         tptr = (*loc).second;
      83              :     }
      84         1140 :     return tptr->indx;
      85         1140 : }
      86              : 
      87              : // start a timer
      88         5056 : void Timing::startTimer(TimerRef t) {
      89         5056 :     if (t >= TimerList.size())
      90            0 :         return;
      91              :     #ifdef IPPL_ENABLE_NSYS_PROFILER
      92              :     PUSH_RANGE(TimerList[t]->name.c_str(), (int)t);
      93              :     #endif
      94         5056 :     TimerList[t]->start();
      95              : }
      96              : 
      97              : // stop a timer, and accumulate it's values
      98         5056 : void Timing::stopTimer(TimerRef t) {
      99         5056 :     if (t >= TimerList.size())
     100            0 :         return;
     101              :     #ifdef IPPL_ENABLE_NSYS_PROFILER
     102              :     nvtxRangePop();
     103              :     #endif
     104         5056 :     TimerList[t]->stop();
     105              : }
     106              : 
     107              : // clear a timer, by turning it off and throwing away its time
     108            0 : void Timing::clearTimer(TimerRef t) {
     109            0 :     if (t >= TimerList.size())
     110            0 :         return;
     111            0 :     TimerList[t]->clear();
     112              : }
     113              : 
     114              : // print out the timing results
     115            0 : void Timing::print() {
     116            0 :     if (TimerList.size() < 1)
     117            0 :         return;
     118              : 
     119              :     // report the average time for each timer
     120            0 :     Inform msg("Timings");
     121            0 :     msg << level1 << "---------------------------------------------";
     122            0 :     msg << "\n";
     123            0 :     msg << "     Timing results for " << ippl::Comm->size() << " nodes:"
     124            0 :         << "\n";
     125            0 :     msg << "---------------------------------------------";
     126            0 :     msg << "\n";
     127              : 
     128              :     {
     129            0 :         TimerInfo* tptr  = TimerList[0].get();
     130            0 :         double walltotal = 0.0;
     131            0 :         ippl::Comm->reduce(tptr->wallTime, walltotal, 1, std::greater<double>());
     132            0 :         size_t lengthName = std::min(tptr->name.length(), 19lu);
     133            0 :         msg << tptr->name.substr(0, lengthName) << std::string().assign(20 - lengthName, '.')
     134            0 :             << " Wall tot = " << std::setw(10) << walltotal << "\n"
     135            0 :             << "\n";
     136              :     }
     137              : 
     138            0 :     for (unsigned int i = 1; i < TimerList.size(); ++i) {
     139            0 :         TimerInfo* tptr = TimerList[i].get();
     140            0 :         double wallmax = 0.0, wallmin = 0.0;
     141            0 :         double wallavg = 0.0;
     142            0 :         ippl::Comm->reduce(tptr->wallTime, wallmax, 1, std::greater<double>());
     143            0 :         ippl::Comm->reduce(tptr->wallTime, wallmin, 1, std::less<double>());
     144            0 :         ippl::Comm->reduce(tptr->wallTime, wallavg, 1, std::plus<double>());
     145            0 :         size_t lengthName = std::min(tptr->name.length(), 19lu);
     146              : 
     147            0 :         msg << tptr->name.substr(0, lengthName) << std::string().assign(20 - lengthName, '.')
     148            0 :             << " Wall max = " << std::setw(10) << wallmax << "\n"
     149            0 :             << std::string().assign(20, ' ') << " Wall avg = " << std::setw(10)
     150            0 :             << wallavg / ippl::Comm->size() << "\n"
     151            0 :             << std::string().assign(20, ' ') << " Wall min = " << std::setw(10) << wallmin << "\n"
     152            0 :             << "\n";
     153              :     }
     154            0 :     msg << "---------------------------------------------";
     155            0 :     msg << endl;
     156            0 : }
     157              : 
     158              : // save the timing results into a file
     159            0 : void Timing::print(const std::string& fn, const std::map<std::string, unsigned int>& problemSize) {
     160              :     std::ofstream* timer_stream;
     161              :     Inform* msg;
     162              : 
     163            0 :     if (TimerList.size() < 1)
     164            0 :         return;
     165              : 
     166            0 :     timer_stream = new std::ofstream;
     167            0 :     timer_stream->open(fn.c_str(), std::ios::out);
     168            0 :     msg = new Inform(0, *timer_stream, 0);
     169              : 
     170            0 :     if (problemSize.size() > 0) {
     171            0 :         *msg << "Problem size:\n";
     172            0 :         for (auto it : problemSize) {
     173            0 :             *msg << "    " << std::setw(10) << it.first << ": " << it.second << "\n";
     174            0 :         }
     175            0 :         *msg << endl;
     176              :     }
     177              : 
     178            0 :     *msg << std::setw(27) << "ranks" << std::setw(11) << "Wall tot\n"
     179            0 :          << std::string().assign(37, '=') << "\n";
     180              :     {
     181            0 :         TimerInfo* tptr  = TimerList[0].get();
     182            0 :         double walltotal = 0.0;
     183            0 :         ippl::Comm->reduce(tptr->wallTime, walltotal, 1, std::greater<double>());
     184            0 :         size_t lengthName = std::min(tptr->name.length(), 19lu);
     185            0 :         *msg << tptr->name.substr(0, lengthName);
     186            0 :         for (int j = lengthName; j < 20; ++j) {
     187            0 :             *msg << ".";
     188              :         }
     189            0 :         *msg << " " << std::setw(6) << ippl::Comm->size() << " " << std::setw(9)
     190            0 :              << std::setprecision(4) << walltotal << "\n";
     191              :     }
     192              : 
     193              :     *msg << "\n"
     194            0 :          << std::setw(27) << "ranks" << std::setw(10) << "Wall max" << std::setw(10) << "Wall min"
     195            0 :          << std::setw(11) << "Wall avg\n"
     196            0 :          << std::string().assign(57, '=') << "\n";
     197            0 :     for (unsigned int i = 0; i < TimerList.size(); ++i) {
     198            0 :         TimerInfo* tptr = TimerList[i].get();
     199            0 :         double wallmax = 0.0, wallmin = 0.0;
     200            0 :         double wallavg = 0.0;
     201            0 :         ippl::Comm->reduce(tptr->wallTime, wallmax, 1, std::greater<double>());
     202            0 :         ippl::Comm->reduce(tptr->wallTime, wallmin, 1, std::less<double>());
     203            0 :         ippl::Comm->reduce(tptr->wallTime, wallavg, 1, std::plus<double>());
     204            0 :         size_t lengthName = std::min(tptr->name.length(), 19lu);
     205            0 :         *msg << tptr->name.substr(0, lengthName);
     206            0 :         for (int j = lengthName; j < 20; ++j) {
     207            0 :             *msg << ".";
     208              :         }
     209            0 :         *msg << " " << std::setw(6) << ippl::Comm->size() << " " << std::setw(9)
     210            0 :              << std::setprecision(4) << wallmax << " " << std::setw(9) << std::setprecision(4)
     211            0 :              << wallmin << " " << std::setw(9) << std::setprecision(4)
     212            0 :              << wallavg / ippl::Comm->size() << endl;
     213              :     }
     214            0 :     timer_stream->close();
     215            0 :     delete msg;
     216            0 :     delete timer_stream;
     217              : }
     218              : 
     219            0 : IpplTimings::IpplTimings() {}
     220            0 : IpplTimings::~IpplTimings() {}
     221              : 
     222            0 : void IpplTimings::stash() {
     223            0 :     PAssert_EQ(stashedInstance.size(), 0);
     224              : 
     225            0 :     stashedInstance.push(instance);
     226            0 :     instance = new Timing();
     227            0 : }
     228              : 
     229            0 : void IpplTimings::pop() {
     230            0 :     PAssert_GT(stashedInstance.size(), 0);
     231              : 
     232            0 :     delete instance;
     233            0 :     instance = stashedInstance.top();
     234            0 :     stashedInstance.pop();
     235            0 : }
        

Generated by: LCOV version 2.0-1