IPPL (Independent Parallel Particle Layer)
IPPL
Loading...
Searching...
No Matches
IpplTimings.cpp
Go to the documentation of this file.
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"
38const uint32_t colors[] = { 0xff00ff00, 0xff0000ff, 0xffffff00, 0xffff00ff, 0xff00ffff, 0xffff0000, 0xffffffff };
39const 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
55std::stack<Timing*> IpplTimings::stashedInstance;
56
60
62 for (TimerMap_t::iterator it = TimerMap.begin(); it != TimerMap.end(); ++it) {
63 it->second = 0;
64 }
65 TimerMap.clear();
66
67 TimerList.clear();
68}
69
70// create a timer, or get one that already exists
72 std::string s(nm);
73 TimerInfo* tptr = 0;
74 TimerMap_t::iterator loc = TimerMap.find(s);
75 if (loc == TimerMap.end()) {
76 tptr = new TimerInfo;
77 tptr->indx = TimerList.size();
78 tptr->name = s;
79 TimerMap.insert(TimerMap_t::value_type(s, tptr));
80 TimerList.push_back(my_auto_ptr<TimerInfo>(tptr));
81 } else {
82 tptr = (*loc).second;
83 }
84 return tptr->indx;
85}
86
87// start a timer
89 if (t >= TimerList.size())
90 return;
91 #ifdef IPPL_ENABLE_NSYS_PROFILER
92 PUSH_RANGE(TimerList[t]->name.c_str(), (int)t);
93 #endif
94 TimerList[t]->start();
95}
96
97// stop a timer, and accumulate it's values
99 if (t >= TimerList.size())
100 return;
101 #ifdef IPPL_ENABLE_NSYS_PROFILER
102 nvtxRangePop();
103 #endif
104 TimerList[t]->stop();
105}
106
107// clear a timer, by turning it off and throwing away its time
109 if (t >= TimerList.size())
110 return;
111 TimerList[t]->clear();
112}
113
114// print out the timing results
116 if (TimerList.size() < 1)
117 return;
118
119 // report the average time for each timer
120 Inform msg("Timings");
121 msg << level1 << "---------------------------------------------";
122 msg << "\n";
123 msg << " Timing results for " << ippl::Comm->size() << " nodes:"
124 << "\n";
125 msg << "---------------------------------------------";
126 msg << "\n";
127
128 {
129 TimerInfo* tptr = TimerList[0].get();
130 double walltotal = 0.0;
131 ippl::Comm->reduce(tptr->wallTime, walltotal, 1, std::greater<double>());
132 size_t lengthName = std::min(tptr->name.length(), 19lu);
133 msg << tptr->name.substr(0, lengthName) << std::string().assign(20 - lengthName, '.')
134 << " Wall tot = " << std::setw(10) << walltotal << "\n"
135 << "\n";
136 }
137
138 for (unsigned int i = 1; i < TimerList.size(); ++i) {
139 TimerInfo* tptr = TimerList[i].get();
140 double wallmax = 0.0, wallmin = 0.0;
141 double wallavg = 0.0;
142 ippl::Comm->reduce(tptr->wallTime, wallmax, 1, std::greater<double>());
143 ippl::Comm->reduce(tptr->wallTime, wallmin, 1, std::less<double>());
144 ippl::Comm->reduce(tptr->wallTime, wallavg, 1, std::plus<double>());
145 size_t lengthName = std::min(tptr->name.length(), 19lu);
146
147 msg << tptr->name.substr(0, lengthName) << std::string().assign(20 - lengthName, '.')
148 << " Wall max = " << std::setw(10) << wallmax << "\n"
149 << std::string().assign(20, ' ') << " Wall avg = " << std::setw(10)
150 << wallavg / ippl::Comm->size() << "\n"
151 << std::string().assign(20, ' ') << " Wall min = " << std::setw(10) << wallmin << "\n"
152 << "\n";
153 }
154 msg << "---------------------------------------------";
155 msg << endl;
156}
157
158// save the timing results into a file
159void Timing::print(const std::string& fn, const std::map<std::string, unsigned int>& problemSize) {
160 std::ofstream* timer_stream;
161 Inform* msg;
162
163 if (TimerList.size() < 1)
164 return;
165
166 timer_stream = new std::ofstream;
167 timer_stream->open(fn.c_str(), std::ios::out);
168 msg = new Inform(0, *timer_stream, 0);
169
170 if (problemSize.size() > 0) {
171 *msg << "Problem size:\n";
172 for (auto it : problemSize) {
173 *msg << " " << std::setw(10) << it.first << ": " << it.second << "\n";
174 }
175 *msg << endl;
176 }
177
178 *msg << std::setw(27) << "ranks" << std::setw(11) << "Wall tot\n"
179 << std::string().assign(37, '=') << "\n";
180 {
181 TimerInfo* tptr = TimerList[0].get();
182 double walltotal = 0.0;
183 ippl::Comm->reduce(tptr->wallTime, walltotal, 1, std::greater<double>());
184 size_t lengthName = std::min(tptr->name.length(), 19lu);
185 *msg << tptr->name.substr(0, lengthName);
186 for (int j = lengthName; j < 20; ++j) {
187 *msg << ".";
188 }
189 *msg << " " << std::setw(6) << ippl::Comm->size() << " " << std::setw(9)
190 << std::setprecision(4) << walltotal << "\n";
191 }
192
193 *msg << "\n"
194 << std::setw(27) << "ranks" << std::setw(10) << "Wall max" << std::setw(10) << "Wall min"
195 << std::setw(11) << "Wall avg\n"
196 << std::string().assign(57, '=') << "\n";
197 for (unsigned int i = 0; i < TimerList.size(); ++i) {
198 TimerInfo* tptr = TimerList[i].get();
199 double wallmax = 0.0, wallmin = 0.0;
200 double wallavg = 0.0;
201 ippl::Comm->reduce(tptr->wallTime, wallmax, 1, std::greater<double>());
202 ippl::Comm->reduce(tptr->wallTime, wallmin, 1, std::less<double>());
203 ippl::Comm->reduce(tptr->wallTime, wallavg, 1, std::plus<double>());
204 size_t lengthName = std::min(tptr->name.length(), 19lu);
205 *msg << tptr->name.substr(0, lengthName);
206 for (int j = lengthName; j < 20; ++j) {
207 *msg << ".";
208 }
209 *msg << " " << std::setw(6) << ippl::Comm->size() << " " << std::setw(9)
210 << std::setprecision(4) << wallmax << " " << std::setw(9) << std::setprecision(4)
211 << wallmin << " " << std::setw(9) << std::setprecision(4)
212 << wallavg / ippl::Comm->size() << endl;
213 }
214 timer_stream->close();
215 delete msg;
216 delete timer_stream;
217}
218
221
223 PAssert_EQ(stashedInstance.size(), 0);
224
226 instance = new Timing();
227}
228
230 PAssert_GT(stashedInstance.size(), 0);
231
232 delete instance;
234 stashedInstance.pop();
235}
Inform & endl(Inform &inf)
Definition Inform.cpp:42
Inform & level1(Inform &inf)
Definition Inform.cpp:48
#define PAssert_EQ(a, b)
Definition PAssert.h:123
#define PAssert_GT(a, b)
Definition PAssert.h:127
std::unique_ptr< mpi::Communicator > Comm
Definition Ippl.h:22
std::string name
Definition IpplTimings.h:83
TimerRef indx
Definition IpplTimings.h:92
double wallTime
Definition IpplTimings.h:86
unsigned int TimerRef
Definition IpplTimings.h:97
void clearTimer(TimerRef)
IpplTimerInfo TimerInfo
TimerMap_t TimerMap
void print()
void stopTimer(TimerRef)
TimerList_t TimerList
void startTimer(TimerRef)
TimerRef getTimer(const char *)
static void stash()
static std::stack< Timing * > stashedInstance
static Timing * instance
static void pop()