LCOV - code coverage report
Current view: top level - src/Utility - IpplTimings.cpp (source / functions) Coverage Total Hit
Test: report.info Lines: 16.8 % 125 21
Test Date: 2025-05-21 12:58:26 Functions: 33.3 % 12 4
Branches: 4.9 % 246 12

             Branch data     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                 :         548 : Timing::Timing()
      58                 :         548 :     : TimerList()
      59                 :         548 :     , 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                 :         344 : Timing::TimerRef Timing::getTimer(const char* nm) {
      72         [ +  - ]:         344 :     std::string s(nm);
      73                 :         344 :     TimerInfo* tptr          = 0;
      74         [ +  - ]:         344 :     TimerMap_t::iterator loc = TimerMap.find(s);
      75         [ +  - ]:         344 :     if (loc == TimerMap.end()) {
      76   [ +  -  +  -  :         344 :         tptr       = new TimerInfo;
             -  +  -  - ]
      77                 :         344 :         tptr->indx = TimerList.size();
      78         [ +  - ]:         344 :         tptr->name = s;
      79   [ +  -  +  - ]:         344 :         TimerMap.insert(TimerMap_t::value_type(s, tptr));
      80         [ +  - ]:         344 :         TimerList.push_back(my_auto_ptr<TimerInfo>(tptr));
      81                 :             :     } else {
      82                 :           0 :         tptr = (*loc).second;
      83                 :             :     }
      84                 :         344 :     return tptr->indx;
      85                 :         344 : }
      86                 :             : 
      87                 :             : // start a timer
      88                 :         336 : void Timing::startTimer(TimerRef t) {
      89         [ -  + ]:         336 :     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                 :         336 :     TimerList[t]->start();
      95                 :             : }
      96                 :             : 
      97                 :             : // stop a timer, and accumulate it's values
      98                 :         252 : void Timing::stopTimer(TimerRef t) {
      99         [ -  + ]:         252 :     if (t >= TimerList.size())
     100                 :           0 :         return;
     101                 :             :     #ifdef IPPL_ENABLE_NSYS_PROFILER
     102                 :             :     nvtxRangePop();
     103                 :             :     #endif
     104                 :         252 :     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