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