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 : }
|