Line data Source code
1 : #include <algorithm>
2 : #include <iomanip>
3 : #include <ios>
4 : #include <map>
5 : #include <sstream>
6 : #include <type_traits>
7 :
8 : #include "Tools/Display/Statistics/Statistics.hpp"
9 : #include "Tools/Display/rang_format/rang_format.h"
10 : #include "Tools/Exception/exception.hpp"
11 :
12 : using namespace spu;
13 : using namespace spu::tools;
14 :
15 : void
16 84 : Statistics::separation1(const bool display_thr, std::ostream& stream)
17 : {
18 : // clang-format off
19 84 : if (display_thr)
20 0 : stream << "# " << rang::style::bold << "---------------------------------------------------------------||------------------------------||--------------------------------||--------------------------------" << rang::style::reset << std::endl;
21 : else
22 84 : stream << "# " << rang::style::bold << "---------------------------------------------------------------||------------------------------||--------------------------------" << rang::style::reset << std::endl;
23 : // clang-format on
24 84 : }
25 :
26 : void
27 126 : Statistics::separation2(const bool display_thr, std::ostream& stream)
28 : {
29 : // clang-format off
30 126 : if (display_thr)
31 0 : stream << "# " << rang::style::bold << "-------------------|-------------------|-----|-------|---------||----------|----------|--------||----------|----------|----------||----------|----------|----------" << rang::style::reset << std::endl;
32 : else
33 126 : stream << "# " << rang::style::bold << "-------------------|-------------------|-----|-------|---------||----------|----------|--------||----------|----------|----------" << rang::style::reset << std::endl;
34 : // clang-format on
35 126 : }
36 :
37 : void
38 42 : Statistics::show_header(const bool display_thr, std::ostream& stream)
39 : {
40 : // clang-format off
41 42 : Statistics::separation1(display_thr, stream);
42 42 : if (display_thr)
43 : {
44 : // stream << "# " << rang::style::bold << "---------------------------------------------------------------||------------------------------||--------------------------------||--------------------------------" << rang::style::reset << std::endl;
45 0 : stream << "# " << rang::style::bold << " Statistics for the given task || Basic statistics || Measured throughput || Measured latency " << rang::style::reset << std::endl;
46 0 : stream << "# " << rang::style::bold << " ('*' = any, '-' = same as previous) || on the task || considering the last socket || " << rang::style::reset << std::endl;
47 : // stream << "# " << rang::style::bold << "---------------------------------------------------------------||------------------------------||--------------------------------||--------------------------------" << rang::style::reset << std::endl;
48 : }
49 : else
50 : {
51 : // stream << "# " << rang::style::bold << "---------------------------------------------------------------||------------------------------||--------------------------------" << rang::style::reset << std::endl;
52 42 : stream << "# " << rang::style::bold << " Statistics for the given task || Basic statistics || Measured latency " << rang::style::reset << std::endl;
53 42 : stream << "# " << rang::style::bold << " ('*' = any, '-' = same as previous) || on the task || " << rang::style::reset << std::endl;
54 : // stream << "# " << rang::style::bold << "---------------------------------------------------------------||------------------------------||--------------------------------" << rang::style::reset << std::endl;
55 : }
56 42 : Statistics::separation1(display_thr, stream);
57 42 : Statistics::separation2(display_thr, stream);
58 42 : if (display_thr)
59 : {
60 : // stream << "# " << rang::style::bold << "-------------------|-------------------|-----|-------|---------||----------|----------|--------||----------|----------|----------||----------|----------|----------" << rang::style::reset << std::endl;
61 0 : stream << "# " << rang::style::bold << " MODULE NAME | TASK NAME | REP | ORDER | TIMER || CALLS | TIME | PERC || AVERAGE | MINIMUM | MAXIMUM || AVERAGE | MINIMUM | MAXIMUM " << rang::style::reset << std::endl;
62 0 : stream << "# " << rang::style::bold << " | | | | || | (s) | (%) || (Mb/s) | (Mb/s) | (Mb/s) || (us) | (us) | (us) " << rang::style::reset << std::endl;
63 : // stream << "# " << rang::style::bold << "-------------------|-------------------|-----|-------|---------||----------|----------|--------||----------|----------|----------||----------|----------|----------" << rang::style::reset << std::endl;
64 : }
65 : else
66 : {
67 : // stream << "# " << rang::style::bold << "-------------------|-------------------|-----|-------|---------||----------|----------|--------||----------|----------|----------" << rang::style::reset << std::endl;
68 42 : stream << "# " << rang::style::bold << " MODULE NAME | TASK NAME | REP | ORDER | TIMER || CALLS | TIME | PERC || AVERAGE | MINIMUM | MAXIMUM " << rang::style::reset << std::endl;
69 42 : stream << "# " << rang::style::bold << " | | | | || | (s) | (%) || (us) | (us) | (us) " << rang::style::reset << std::endl;
70 : // stream << "# " << rang::style::bold << "-------------------|-------------------|-----|-------|---------||----------|----------|--------||----------|----------|----------" << rang::style::reset << std::endl;
71 : }
72 42 : Statistics::separation2(display_thr, stream);
73 : // clang-format on
74 42 : }
75 :
76 : void
77 264 : Statistics::show_task(const float total_sec,
78 : const std::string& module_name,
79 : const std::string& task_name,
80 : const bool task_replicability,
81 : const int task_order,
82 : const size_t task_n_elmts,
83 : const uint32_t task_n_calls,
84 : const std::chrono::nanoseconds task_tot_duration,
85 : const std::chrono::nanoseconds task_min_duration,
86 : const std::chrono::nanoseconds task_max_duration,
87 : const bool display_thr,
88 : std::ostream& stream)
89 : {
90 : // clang-format off
91 264 : if (task_n_calls == 0)
92 14 : return;
93 :
94 250 : auto tot_dur = ((float)task_tot_duration.count()) * 0.000000001f;
95 250 : auto percent = (tot_dur / total_sec) * 100.f;
96 250 : auto avg_thr = (float)(task_n_calls * task_n_elmts) / ((float)task_tot_duration.count() * 0.001f);
97 250 : auto min_thr = (float)(1.f * task_n_elmts) / ((float)task_max_duration.count() * 0.001f);
98 250 : auto max_thr = (float)(1.f * task_n_elmts) / ((float)task_min_duration.count() * 0.001f);
99 250 : auto avg_lat = (float)(task_tot_duration.count() * 0.001f) / task_n_calls;
100 250 : auto min_lat = (float)(task_min_duration.count() * 0.001f);
101 250 : auto max_lat = (float)(task_max_duration.count() * 0.001f);
102 :
103 : #ifdef _WIN32
104 : auto P = 1;
105 : #else
106 250 : auto P = 2;
107 : #endif
108 :
109 250 : unsigned l1 = 99999999;
110 250 : float l2 = 99999.99f;
111 :
112 250 : std::stringstream ssmodule, ssprocess, ssrep, ssorder, sssp, ssn_calls, sstot_dur, sspercent;
113 250 : std::stringstream ssavg_thr, ssmin_thr, ssmax_thr;
114 250 : std::stringstream ssavg_lat, ssmin_lat, ssmax_lat;
115 :
116 250 : ssmodule << std::setprecision( 2) << std::fixed << std::setw(18) << module_name;
117 250 : ssprocess << std::setprecision( 2) << std::fixed << std::setw(17) << task_name;
118 250 : ssrep << std::setprecision( 2) << std::fixed << std::setw( 3) << (task_replicability ? "yes" : "no");
119 250 : if (task_order >= 0)
120 208 : ssorder << std::setprecision( 2) << std::fixed << std::setw( 5) << task_order;
121 : else
122 42 : ssorder << std::setprecision( 2) << std::fixed << std::setw( 5) << "*";
123 250 : sssp << std::setprecision( 2) << std::fixed << std::setw( 7) << "*";
124 250 : ssn_calls << std::setprecision(task_n_calls > l1 ? P : 2) << (task_n_calls > l1 ? std::scientific : std::fixed) << std::setw( 8) << task_n_calls;
125 250 : sstot_dur << std::setprecision(tot_dur > l1 ? P : 2) << (tot_dur > l1 ? std::scientific : std::fixed) << std::setw( 8) << tot_dur;
126 250 : sspercent << std::setprecision( 2) << std::fixed << std::setw( 6) << percent;
127 250 : ssavg_thr << std::setprecision(avg_thr > l1 ? P : 2) << (avg_thr > l2 ? std::scientific : std::fixed) << std::setw( 8) << avg_thr;
128 250 : ssmin_thr << std::setprecision(min_thr > l1 ? P : 2) << (min_thr > l2 ? std::scientific : std::fixed) << std::setw( 8) << min_thr;
129 250 : ssmax_thr << std::setprecision(max_thr > l1 ? P : 2) << (max_thr > l2 ? std::scientific : std::fixed) << std::setw( 8) << max_thr;
130 250 : ssavg_lat << std::setprecision(avg_lat > l1 ? P : 2) << (avg_lat > l2 ? std::scientific : std::fixed) << std::setw( 8) << avg_lat;
131 250 : ssmin_lat << std::setprecision(min_lat > l1 ? P : 2) << (min_lat > l2 ? std::scientific : std::fixed) << std::setw( 8) << min_lat;
132 250 : ssmax_lat << std::setprecision(max_lat > l1 ? P : 2) << (max_lat > l2 ? std::scientific : std::fixed) << std::setw( 8) << max_lat;
133 :
134 250 : stream << "# ";
135 250 : stream << ssmodule .str() << rang::style::bold << " | " << rang::style::reset
136 500 : << ssprocess.str() << rang::style::bold << " | " << rang::style::reset
137 500 : << ssrep .str() << rang::style::bold << " | " << rang::style::reset
138 500 : << ssorder .str() << rang::style::bold << " | " << rang::style::reset
139 500 : << sssp .str() << rang::style::bold << " || " << rang::style::reset
140 500 : << ssn_calls.str() << rang::style::bold << " | " << rang::style::reset
141 250 : << sstot_dur.str() << rang::style::bold << " | " << rang::style::reset;
142 :
143 250 : if (percent > 50.0f) stream << rang::fg::red << sspercent.str() << rang::style::reset;
144 184 : else if (percent > 25.0f) stream << rang::fg::yellow << sspercent.str() << rang::style::reset;
145 155 : else if (percent > 12.5f) stream << rang::fg::green << sspercent.str() << rang::style::reset;
146 116 : else if (percent < 5.0f) stream << rang::fg::gray << sspercent.str() << rang::style::reset;
147 51 : else stream << sspercent.str();
148 :
149 250 : if (display_thr)
150 0 : stream << rang::style::bold << " || " << rang::style::reset
151 0 : << ssavg_thr.str() << rang::style::bold << " | " << rang::style::reset
152 0 : << ssmin_thr.str() << rang::style::bold << " | " << rang::style::reset
153 0 : << ssmax_thr.str() << rang::style::bold << " || " << rang::style::reset
154 0 : << ssavg_lat.str() << rang::style::bold << " | " << rang::style::reset
155 0 : << ssmin_lat.str() << rang::style::bold << " | " << rang::style::reset
156 0 : << ssmax_lat.str() << ""
157 0 : << std::endl;
158 : else
159 250 : stream << rang::style::bold << " || " << rang::style::reset
160 500 : << ssavg_lat.str() << rang::style::bold << " | " << rang::style::reset
161 500 : << ssmin_lat.str() << rang::style::bold << " | " << rang::style::reset
162 500 : << ssmax_lat.str() << ""
163 250 : << std::endl;
164 : // clang-format on
165 250 : }
166 :
167 : void
168 0 : Statistics::show_timer(const float total_sec,
169 : const uint32_t task_n_calls,
170 : const size_t timer_n_elmts,
171 : const std::string& timer_name,
172 : const uint32_t timer_n_calls,
173 : const std::chrono::nanoseconds timer_tot_duration,
174 : const std::chrono::nanoseconds timer_min_duration,
175 : const std::chrono::nanoseconds timer_max_duration,
176 : std::ostream& stream)
177 : {
178 : // clang-format off
179 0 : if (task_n_calls == 0 || timer_n_calls == 0)
180 0 : return;
181 :
182 0 : auto rn_elmts = (timer_n_elmts * task_n_calls) / timer_n_calls;
183 0 : auto rtot_dur = ((float)timer_tot_duration.count()) * 0.000000001f;
184 0 : auto rpercent = (rtot_dur / total_sec) * 100.f;
185 0 : auto ravg_thr = (float)(timer_n_calls * rn_elmts) / ((float)timer_tot_duration.count() * 0.001f);
186 0 : auto rmin_thr = (float)(1.f * rn_elmts) / ((float)timer_max_duration.count() * 0.001f);
187 0 : auto rmax_thr = (float)(1.f * rn_elmts) / ((float)timer_min_duration.count() * 0.001f);
188 0 : auto ravg_lat = (float)(timer_tot_duration.count() * 0.001f) / timer_n_calls;
189 0 : auto rmin_lat = (float)(timer_min_duration.count() * 0.001f);
190 0 : auto rmax_lat = (float)(timer_max_duration.count() * 0.001f);
191 :
192 : #ifdef _WIN32
193 : auto P = 1;
194 : #else
195 0 : auto P = 2;
196 : #endif
197 :
198 0 : unsigned l1 = 99999999;
199 0 : float l2 = 99999.99f;
200 :
201 0 : std::stringstream spaces, ssprocess, ssrep, ssorder, sssp, ssrn_calls, ssrtot_dur, ssrpercent;
202 0 : std::stringstream ssravg_thr, ssrmin_thr, ssrmax_thr;
203 0 : std::stringstream ssravg_lat, ssrmin_lat, ssrmax_lat;
204 :
205 0 : spaces << std::fixed << std::setw(18) << "-";
206 0 : ssprocess << std::setprecision( 2) << std::fixed << std::setw(17) << "-";
207 0 : ssrep << std::setprecision( 2) << std::fixed << std::setw( 3) << "-";
208 0 : ssorder << std::setprecision( 2) << std::fixed << std::setw( 5) << "-";
209 0 : sssp << std::setprecision( 2) << std::fixed << std::setw( 7) << timer_name;
210 0 : ssrn_calls << std::setprecision(timer_n_calls > l1 ? P : 2) << (timer_n_calls > l1 ? std::scientific : std::fixed) << std::setw( 8) << timer_n_calls;
211 0 : ssrtot_dur << std::setprecision(rtot_dur > l1 ? P : 2) << (rtot_dur > l1 ? std::scientific : std::fixed) << std::setw( 8) << rtot_dur;
212 0 : ssrpercent << std::setprecision( 2) << std::fixed << std::setw( 6) << rpercent;
213 0 : ssravg_thr << std::setprecision(ravg_thr > l1 ? P : 2) << (ravg_thr > l2 ? std::scientific : std::fixed) << std::setw( 8) << ravg_thr;
214 0 : ssrmin_thr << std::setprecision(rmin_thr > l1 ? P : 2) << (rmin_thr > l2 ? std::scientific : std::fixed) << std::setw( 8) << rmin_thr;
215 0 : ssrmax_thr << std::setprecision(rmax_thr > l1 ? P : 2) << (rmax_thr > l2 ? std::scientific : std::fixed) << std::setw( 8) << rmax_thr;
216 0 : ssravg_lat << std::setprecision(ravg_lat > l1 ? P : 2) << (ravg_lat > l2 ? std::scientific : std::fixed) << std::setw( 8) << ravg_lat;
217 0 : ssrmin_lat << std::setprecision(rmin_lat > l1 ? P : 2) << (rmin_lat > l2 ? std::scientific : std::fixed) << std::setw( 8) << rmin_lat;
218 0 : ssrmax_lat << std::setprecision(rmax_lat > l1 ? P : 2) << (rmax_lat > l2 ? std::scientific : std::fixed) << std::setw( 8) << rmax_lat;
219 :
220 0 : stream << "# ";
221 0 : stream << spaces.str() << rang::style::bold << " | " << rang::style::reset
222 0 : << rang::style::italic << ssprocess .str() << rang::style::reset << rang::style::bold << " | " << rang::style::reset
223 0 : << rang::style::italic << ssrep .str() << rang::style::reset << rang::style::bold << " | " << rang::style::reset
224 0 : << rang::style::italic << ssorder .str() << rang::style::reset << rang::style::bold << " | " << rang::style::reset
225 0 : << rang::style::italic << sssp .str() << rang::style::reset << rang::style::bold << " || " << rang::style::reset
226 0 : << rang::style::italic << ssrn_calls.str() << rang::style::reset << rang::style::bold << " | " << rang::style::reset
227 0 : << rang::style::italic << ssrtot_dur.str() << rang::style::reset << rang::style::bold << " | " << rang::style::reset
228 0 : << rang::style::italic << ssrpercent.str() << rang::style::reset << rang::style::bold << " || " << rang::style::reset
229 0 : << rang::style::italic << ssravg_thr.str() << rang::style::reset << rang::style::bold << " | " << rang::style::reset
230 0 : << rang::style::italic << ssrmin_thr.str() << rang::style::reset << rang::style::bold << " | " << rang::style::reset
231 0 : << rang::style::italic << ssrmax_thr.str() << rang::style::reset << rang::style::bold << " || " << rang::style::reset
232 0 : << rang::style::italic << ssravg_lat.str() << rang::style::reset << rang::style::bold << " | " << rang::style::reset
233 0 : << rang::style::italic << ssrmin_lat.str() << rang::style::reset << rang::style::bold << " | " << rang::style::reset
234 0 : << rang::style::italic << ssrmax_lat.str() << rang::style::reset << ""
235 0 : << std::endl;
236 : // clang-format on
237 0 : }
238 :
239 : template<class MODULE_OR_TASK>
240 : void
241 : Statistics::show(std::vector<MODULE_OR_TASK*> modules_or_tasks,
242 : const bool ordered,
243 : const bool display_thr,
244 : std::ostream& stream)
245 : {
246 : std::stringstream message;
247 : message << "The 'Statistics::show' method expect a 'std::vector' of 'module::Module' or 'runtime::Task'.";
248 : throw tools::invalid_argument(__FILE__, __LINE__, __func__, message.str());
249 : }
250 :
251 : namespace spu
252 : {
253 : namespace tools
254 : {
255 :
256 : template<>
257 : void
258 0 : Statistics::show<module::Module>(std::vector<module::Module*> modules,
259 : const bool ordered,
260 : const bool display_thr,
261 : std::ostream& stream)
262 : {
263 0 : Statistics::show_modules<module::Module>(modules, ordered, display_thr, stream);
264 0 : }
265 :
266 : template<>
267 : void
268 0 : Statistics::show<const module::Module>(std::vector<const module::Module*> modules,
269 : const bool ordered,
270 : const bool display_thr,
271 : std::ostream& stream)
272 : {
273 0 : Statistics::show_modules<const module::Module>(modules, ordered, display_thr, stream);
274 0 : }
275 :
276 : template<>
277 : void
278 11 : Statistics::show<runtime::Task>(std::vector<runtime::Task*> tasks,
279 : const bool ordered,
280 : const bool display_thr,
281 : std::ostream& stream)
282 : {
283 11 : Statistics::show_tasks<runtime::Task>(tasks, ordered, display_thr, stream);
284 11 : }
285 :
286 : template<>
287 : void
288 0 : Statistics::show<const runtime::Task>(std::vector<const runtime::Task*> tasks,
289 : const bool ordered,
290 : const bool display_thr,
291 : std::ostream& stream)
292 : {
293 0 : Statistics::show_tasks<const runtime::Task>(tasks, ordered, display_thr, stream);
294 0 : }
295 :
296 : }
297 : }
298 :
299 : template<class MODULE>
300 : void
301 0 : Statistics::show_modules(std::vector<MODULE*> modules, const bool ordered, const bool display_thr, std::ostream& stream)
302 : {
303 0 : std::vector<const runtime::Task*> tasks;
304 0 : for (auto& m : modules)
305 0 : if (m != nullptr)
306 0 : for (auto& t : m->tasks)
307 0 : if (t->get_n_calls()) tasks.push_back(t.get());
308 :
309 0 : Statistics::show_tasks(tasks, ordered, display_thr, stream);
310 0 : }
311 :
312 : template<class TASK>
313 : void
314 11 : Statistics::show_tasks(std::vector<TASK*> tasks, const bool ordered, const bool display_thr, std::ostream& stream)
315 : {
316 70 : for (size_t t = 0; t < tasks.size(); t++)
317 59 : if (tasks[t] == nullptr) tasks.erase(tasks.begin() + t);
318 :
319 11 : std::map<const spu::runtime::Task*, size_t> tasks_order;
320 70 : for (size_t t = 0; t < tasks.size(); t++)
321 59 : tasks_order[(const spu::runtime::Task*)tasks[t]] = t;
322 :
323 11 : if (ordered)
324 : {
325 0 : std::sort(tasks.begin(),
326 : tasks.end(),
327 0 : [](const runtime::Task* t1, const runtime::Task* t2)
328 0 : { return t1->get_duration_total() > t2->get_duration_total(); });
329 : }
330 :
331 11 : auto ttask_tot_duration = std::chrono::nanoseconds(0);
332 11 : auto ttask_min_duration = std::chrono::nanoseconds(0);
333 11 : auto ttask_max_duration = std::chrono::nanoseconds(0);
334 :
335 70 : for (auto* t : tasks)
336 59 : ttask_tot_duration += t->get_duration_total();
337 11 : auto total_sec = ((float)ttask_tot_duration.count()) * 0.000000001f;
338 :
339 11 : if (ttask_tot_duration.count())
340 : {
341 11 : Statistics::show_header(display_thr, stream);
342 :
343 11 : size_t ttask_n_elmts = 0;
344 11 : uint32_t ttask_n_calls = 0;
345 :
346 11 : auto is_first = true;
347 70 : for (auto* t : tasks)
348 : {
349 59 : auto task_n_elmts = t->sockets.end()[-2]->get_n_elmts();
350 59 : auto task_n_calls = t->get_n_calls();
351 :
352 59 : if (is_first)
353 : {
354 11 : if (task_n_calls)
355 : {
356 11 : ttask_n_elmts = task_n_elmts;
357 11 : ttask_n_calls = task_n_calls;
358 11 : is_first = false;
359 : }
360 : }
361 : else
362 : {
363 48 : ttask_n_elmts = task_n_elmts ? std::min(ttask_n_elmts, task_n_elmts) : ttask_n_elmts;
364 48 : ttask_n_calls = task_n_calls ? std::min(ttask_n_calls, task_n_calls) : ttask_n_calls;
365 : }
366 : }
367 :
368 11 : bool all_replicable = true;
369 70 : for (auto* t : tasks)
370 : {
371 114 : auto module_name = t->get_module().get_custom_name().empty() ? t->get_module().get_short_name()
372 55 : : t->get_module().get_custom_name();
373 59 : auto task_n_elmts = t->sockets.end()[-2]->get_n_elmts();
374 59 : auto task_name = t->get_name();
375 59 : bool task_replicability = t->is_replicable();
376 59 : if (!task_replicability) all_replicable = false;
377 59 : auto task_n_calls = t->get_n_calls();
378 59 : auto task_tot_duration = t->get_duration_total();
379 59 : auto task_min_duration = t->get_duration_min();
380 59 : auto task_max_duration = t->get_duration_max();
381 :
382 59 : ttask_min_duration += (task_min_duration * task_n_calls) / ttask_n_calls;
383 59 : ttask_max_duration += (task_max_duration * task_n_calls) / ttask_n_calls;
384 :
385 118 : Statistics::show_task(total_sec,
386 : module_name,
387 : task_name,
388 : task_replicability,
389 59 : tasks_order[t],
390 : task_n_elmts,
391 : task_n_calls,
392 : task_tot_duration,
393 : task_min_duration,
394 : task_max_duration,
395 : display_thr,
396 : stream);
397 :
398 59 : auto task_total_sec = ((float)task_tot_duration.count()) * 0.000000001f;
399 :
400 59 : auto timers_name = t->get_timers_name();
401 59 : auto timers_n_elmts = task_n_elmts;
402 59 : auto timers_n_calls = t->get_timers_n_calls();
403 59 : auto timers_tot_duration = t->get_timers_total();
404 59 : auto timers_min_duration = t->get_timers_min();
405 59 : auto timers_max_duration = t->get_timers_max();
406 :
407 59 : for (size_t i = 0; i < timers_name.size(); i++)
408 : {
409 0 : Statistics::show_timer(task_total_sec,
410 : task_n_calls,
411 : timers_n_elmts,
412 0 : timers_name[i],
413 0 : timers_n_calls[i],
414 0 : timers_tot_duration[i],
415 0 : timers_min_duration[i],
416 0 : timers_max_duration[i],
417 : stream);
418 : }
419 : }
420 11 : Statistics::separation2(display_thr, stream);
421 :
422 11 : Statistics::show_task(total_sec,
423 : "TOTAL",
424 : "*",
425 : all_replicable,
426 : -1,
427 : ttask_n_elmts,
428 : ttask_n_calls,
429 : ttask_tot_duration,
430 : ttask_min_duration,
431 : ttask_max_duration,
432 : display_thr,
433 : stream);
434 : }
435 : else
436 : {
437 0 : stream << rang::tag::comment << rang::tag::info
438 0 : << "Statistics are unavailable. Did you enable the statistics in the tasks?" << std::endl;
439 : }
440 11 : }
441 :
442 : template<class MODULE_OR_TASK>
443 : void
444 : Statistics::show(std::vector<std::vector<MODULE_OR_TASK*>> modules_or_tasks,
445 : const bool ordered,
446 : const bool display_thr,
447 : std::ostream& stream)
448 : {
449 : std::stringstream message;
450 : message << "The 'Statistics::show' method expect a 'std::vector' of 'std::vector' of 'module::Module' or "
451 : << "'runtime::Task'.";
452 : throw tools::invalid_argument(__FILE__, __LINE__, __func__, message.str());
453 : }
454 :
455 : namespace spu
456 : {
457 : namespace tools
458 : {
459 :
460 : template<>
461 : void
462 2 : Statistics::show<module::Module>(std::vector<std::vector<module::Module*>> modules,
463 : const bool ordered,
464 : const bool display_thr,
465 : std::ostream& stream)
466 : {
467 2 : Statistics::show_modules<module::Module>(modules, ordered, display_thr, stream);
468 2 : }
469 :
470 : template<>
471 : void
472 0 : Statistics::show<const module::Module>(std::vector<std::vector<const module::Module*>> modules,
473 : const bool ordered,
474 : const bool display_thr,
475 : std::ostream& stream)
476 : {
477 0 : Statistics::show_modules<const module::Module>(modules, ordered, display_thr, stream);
478 0 : }
479 :
480 : template<>
481 : void
482 29 : Statistics::show<runtime::Task>(std::vector<std::vector<runtime::Task*>> tasks,
483 : const bool ordered,
484 : const bool display_thr,
485 : std::ostream& stream)
486 : {
487 29 : Statistics::show_tasks<runtime::Task>(tasks, ordered, display_thr, stream);
488 29 : }
489 :
490 : template<>
491 : void
492 0 : Statistics::show<const runtime::Task>(std::vector<std::vector<const runtime::Task*>> tasks,
493 : const bool ordered,
494 : const bool display_thr,
495 : std::ostream& stream)
496 : {
497 0 : Statistics::show_tasks<const runtime::Task>(tasks, ordered, display_thr, stream);
498 0 : }
499 :
500 : }
501 : }
502 :
503 : template<class MODULE>
504 : void
505 2 : Statistics::show_modules(std::vector<std::vector<MODULE*>> modules,
506 : const bool ordered,
507 : const bool display_thr,
508 : std::ostream& stream)
509 : {
510 2 : std::vector<std::vector<const runtime::Task*>> tasks;
511 33 : for (auto& vm : modules)
512 31 : if (vm.size() > 0 && vm[0] != nullptr)
513 : {
514 31 : auto& tasks0 = vm[0]->tasks;
515 76 : for (size_t t = 0; t < tasks0.size(); t++)
516 : {
517 45 : std::vector<const runtime::Task*> tsk;
518 90 : for (auto& m : vm)
519 45 : tsk.push_back(m->tasks[t].get());
520 45 : tasks.push_back(tsk);
521 : }
522 : }
523 :
524 2 : Statistics::show_tasks(tasks, ordered, display_thr, stream);
525 2 : }
526 :
527 : template<class TASK>
528 : void
529 31 : Statistics::show_tasks(std::vector<std::vector<TASK*>> tasks,
530 : const bool ordered,
531 : const bool display_thr,
532 : std::ostream& stream)
533 : {
534 : using namespace std::chrono;
535 :
536 31 : if (tasks.size())
537 220 : for (size_t t = 0; t < tasks[0].size(); t++)
538 189 : if (tasks[0][t] == nullptr)
539 0 : for (size_t i = 0; i < tasks.size(); i++)
540 0 : tasks[i].erase(tasks[i].begin() + t);
541 :
542 31 : std::map<const spu::runtime::Task*, size_t> tasks_order;
543 31 : if (tasks.size())
544 194 : for (size_t t = 0; t < tasks.size(); t++)
545 163 : tasks_order[(const spu::runtime::Task*)tasks[t][0]] = t;
546 :
547 31 : if (ordered)
548 : {
549 31 : std::sort(tasks.begin(),
550 : tasks.end(),
551 442 : [](const std::vector<TASK*>& t1, const std::vector<TASK*>& t2)
552 : {
553 442 : auto total1 = nanoseconds(0);
554 442 : auto total2 = nanoseconds(0);
555 5113 : for (auto* t : t1)
556 4671 : total1 += t->get_duration_total();
557 5113 : for (auto* t : t2)
558 4671 : total2 += t->get_duration_total();
559 884 : return total1 > total2;
560 : });
561 : }
562 :
563 31 : auto ttask_tot_duration = nanoseconds(0);
564 31 : auto ttask_min_duration = nanoseconds(0);
565 31 : auto ttask_max_duration = nanoseconds(0);
566 :
567 194 : for (auto& vt : tasks)
568 1636 : for (auto* t : vt)
569 1473 : ttask_tot_duration += t->get_duration_total();
570 31 : auto total_sec = ((float)ttask_tot_duration.count()) * 0.000000001f;
571 :
572 31 : if (ttask_tot_duration.count())
573 : {
574 31 : Statistics::show_header(display_thr, stream);
575 :
576 31 : size_t ttask_n_elmts = 0;
577 31 : auto ttask_n_calls = 0;
578 :
579 31 : auto is_first = true;
580 194 : for (auto& vt : tasks)
581 : {
582 163 : auto task_n_elmts = vt[0]->sockets.size() >= 2 ? vt[0]->sockets.end()[-2]->get_n_elmts() : 0;
583 163 : auto task_n_calls = 0;
584 :
585 1636 : for (auto* t : vt)
586 1473 : task_n_calls += t->get_n_calls();
587 :
588 163 : if (is_first)
589 : {
590 31 : if (task_n_calls)
591 : {
592 31 : ttask_n_elmts = task_n_elmts;
593 31 : ttask_n_calls = task_n_calls;
594 31 : is_first = false;
595 : }
596 : }
597 : else
598 : {
599 132 : ttask_n_elmts = task_n_elmts ? std::min(ttask_n_elmts, task_n_elmts) : ttask_n_elmts;
600 132 : ttask_n_calls = task_n_calls ? std::min(ttask_n_calls, task_n_calls) : ttask_n_calls;
601 : }
602 : }
603 :
604 31 : bool all_replicable = true;
605 194 : for (auto& vt : tasks)
606 : {
607 292 : auto module_name = vt[0]->get_module().get_custom_name().empty() ? vt[0]->get_module().get_short_name()
608 129 : : vt[0]->get_module().get_custom_name();
609 163 : auto task_n_elmts = vt[0]->sockets.size() >= 2 ? vt[0]->sockets.end()[-2]->get_n_elmts() : 0;
610 163 : auto task_name = vt[0]->get_name();
611 163 : bool task_replicability = vt[0]->is_replicable();
612 163 : if (!task_replicability) all_replicable = false;
613 163 : auto task_n_calls = 0;
614 163 : auto task_tot_duration = nanoseconds(0);
615 163 : auto task_min_duration = ttask_tot_duration;
616 163 : auto task_max_duration = nanoseconds(0);
617 :
618 1636 : for (auto* t : vt)
619 : {
620 1473 : task_n_calls += t->get_n_calls();
621 1473 : task_tot_duration += t->get_duration_total();
622 1473 : task_min_duration = std::min(task_min_duration, t->get_duration_min());
623 1473 : task_max_duration = std::max(task_max_duration, t->get_duration_max());
624 : }
625 :
626 163 : ttask_min_duration += (task_min_duration * task_n_calls) / ttask_n_calls;
627 163 : ttask_max_duration += (task_max_duration * task_n_calls) / ttask_n_calls;
628 :
629 326 : Statistics::show_task(total_sec,
630 : module_name,
631 : task_name,
632 : task_replicability,
633 163 : tasks_order[vt[0]],
634 : task_n_elmts,
635 : task_n_calls,
636 : task_tot_duration,
637 : task_min_duration,
638 : task_max_duration,
639 : display_thr,
640 : stream);
641 :
642 163 : auto task_total_sec = ((float)task_tot_duration.count()) * 0.000000001f;
643 :
644 163 : auto timers_name = vt[0]->get_timers_name();
645 163 : auto timers_n_elmts = task_n_elmts;
646 163 : auto timers_n_calls = std::vector<uint32_t>(timers_name.size(), 0);
647 163 : auto timers_tot_duration = std::vector<nanoseconds>(timers_name.size(), nanoseconds(0));
648 163 : auto timers_min_duration = std::vector<nanoseconds>(timers_name.size(), ttask_tot_duration);
649 163 : auto timers_max_duration = std::vector<nanoseconds>(timers_name.size(), nanoseconds(0));
650 :
651 163 : for (size_t tn = 0; tn < vt[0]->get_timers_name().size(); tn++)
652 : {
653 0 : for (auto* t : vt)
654 : {
655 0 : timers_n_calls[tn] += t->get_timers_n_calls()[tn];
656 0 : timers_tot_duration[tn] += t->get_timers_total()[tn];
657 0 : timers_min_duration[tn] = std::min(task_min_duration, t->get_timers_min()[tn]);
658 0 : timers_max_duration[tn] = std::max(task_max_duration, t->get_timers_max()[tn]);
659 : }
660 :
661 0 : Statistics::show_timer(task_total_sec,
662 : task_n_calls,
663 : timers_n_elmts,
664 0 : timers_name[tn],
665 : timers_n_calls[tn],
666 : timers_tot_duration[tn],
667 : timers_min_duration[tn],
668 : timers_max_duration[tn],
669 : stream);
670 : }
671 : }
672 31 : Statistics::separation2(display_thr, stream);
673 :
674 31 : Statistics::show_task(total_sec,
675 : "TOTAL",
676 : "*",
677 : all_replicable,
678 : -1,
679 : ttask_n_elmts,
680 : ttask_n_calls,
681 : ttask_tot_duration,
682 : ttask_min_duration,
683 : ttask_max_duration,
684 : display_thr,
685 : stream);
686 : }
687 : else
688 : {
689 0 : stream << rang::tag::comment << rang::tag::info
690 0 : << "Statistics are unavailable. Did you enable the statistics in the tasks?" << std::endl;
691 : }
692 31 : }
|