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