Line data Source code
1 : #include <algorithm>
2 : #include <iomanip>
3 : #include <ios>
4 : #include <iostream>
5 : #include <rang.hpp>
6 : #include <sstream>
7 : #include <typeinfo>
8 :
9 : #include "Module/Module.hpp"
10 : #include "Runtime/Socket/Socket.hpp"
11 : #include "Runtime/Task/Task.hpp"
12 : #include "Tools/Exception/exception.hpp"
13 :
14 : using namespace spu;
15 : using namespace spu::runtime;
16 :
17 3071 : Task::Task(module::Module& module,
18 : const std::string& name,
19 : const bool autoalloc,
20 : const bool stats,
21 : const bool fast,
22 3071 : const bool debug)
23 3071 : : module(&module)
24 3071 : , name(name)
25 3071 : , autoalloc(autoalloc)
26 3071 : , stats(stats)
27 3071 : , fast(fast)
28 3071 : , debug(debug)
29 3071 : , debug_hex(false)
30 3071 : , replicable(module.is_clonable())
31 3071 : , debug_limit(-1)
32 3071 : , debug_precision(2)
33 3071 : , debug_frame_max(-1)
34 3071 : , codelet(
35 0 : [](module::Module& m, Task& t, const size_t frame_id) -> int
36 : {
37 0 : throw tools::unimplemented_error(__FILE__, __LINE__, __func__);
38 : return 0;
39 : })
40 3071 : , n_input_sockets(0)
41 3071 : , n_output_sockets(0)
42 3071 : , n_fwd_sockets(0)
43 3071 : , status(module.get_n_waves())
44 3071 : , n_calls(0)
45 3071 : , duration_total(std::chrono::nanoseconds(0))
46 3071 : , duration_min(std::chrono::nanoseconds(0))
47 3071 : , duration_max(std::chrono::nanoseconds(0))
48 9213 : , last_input_socket(nullptr)
49 : {
50 3071 : }
51 :
52 : Socket&
53 0 : Task::operator[](const std::string& sck_name)
54 : {
55 0 : std::string s_name = sck_name;
56 0 : s_name.erase(remove(s_name.begin(), s_name.end(), ' '), s_name.end());
57 :
58 0 : auto it = find_if(this->sockets.begin(),
59 : this->sockets.end(),
60 0 : [s_name](std::shared_ptr<runtime::Socket> s) { return s->get_name() == s_name; });
61 :
62 0 : if (it == this->sockets.end())
63 : {
64 0 : std::stringstream message;
65 0 : message << "runtime::Socket '" << s_name << "' not found for task '" << this->get_name() << "'.";
66 0 : throw tools::invalid_argument(__FILE__, __LINE__, __func__, message.str());
67 0 : }
68 :
69 0 : return *it->get();
70 0 : }
71 :
72 : void
73 68785 : Task::set_autoalloc(const bool autoalloc)
74 : {
75 68785 : if (autoalloc != this->autoalloc)
76 : {
77 0 : this->autoalloc = autoalloc;
78 :
79 0 : if (!autoalloc)
80 : {
81 0 : this->out_buffers.clear();
82 0 : for (auto& s : sockets)
83 0 : if (s->get_type() == socket_t::SOUT && s->get_name() != "status") s->dataptr = nullptr;
84 : }
85 : else
86 : {
87 0 : for (auto& s : sockets)
88 0 : if (s->get_type() == socket_t::SOUT && s->get_name() != "status")
89 : {
90 0 : out_buffers.push_back(buffer(s->databytes));
91 0 : s->dataptr = out_buffers.back().data();
92 : }
93 : }
94 : }
95 68785 : }
96 :
97 : void
98 72284 : Task::set_stats(const bool stats)
99 : {
100 72284 : this->stats = stats;
101 72284 : }
102 :
103 : void
104 76480 : Task::set_fast(const bool fast)
105 : {
106 76480 : this->fast = fast;
107 277127 : for (size_t i = 0; i < sockets.size(); i++)
108 200647 : sockets[i]->set_fast(this->fast);
109 76480 : }
110 :
111 : void
112 72192 : Task::set_debug(const bool debug)
113 : {
114 72192 : this->debug = debug;
115 72192 : }
116 :
117 : void
118 0 : Task::set_debug_hex(const bool debug_hex)
119 : {
120 0 : this->debug_hex = debug_hex;
121 0 : }
122 :
123 : void
124 72192 : Task::set_debug_limit(const uint32_t limit)
125 : {
126 72192 : this->debug_limit = (int32_t)limit;
127 72192 : }
128 :
129 : void
130 0 : Task::set_debug_precision(const uint8_t prec)
131 : {
132 0 : this->debug_precision = prec;
133 0 : }
134 :
135 : void
136 0 : Task::set_debug_frame_max(const uint32_t limit)
137 : {
138 0 : this->debug_frame_max = limit;
139 0 : }
140 :
141 : // trick to compile on the GNU compiler version 4 (where 'std::hexfloat' is unavailable)
142 : #if !defined(__clang__) && !defined(__llvm__) && defined(__GNUC__) && defined(__cplusplus) && __GNUC__ < 5
143 : namespace std
144 : {
145 : class Hexfloat
146 : {
147 : public:
148 : void message(std::ostream& os) const { os << " /!\\ 'std::hexfloat' is not supported by this compiler. /!\\ "; }
149 : };
150 : Hexfloat hexfloat;
151 : }
152 : std::ostream&
153 : operator<<(std::ostream& os, const std::Hexfloat& obj)
154 : {
155 : obj.message(os);
156 : return os;
157 : }
158 : #endif
159 :
160 : template<typename T>
161 : static inline void
162 405 : display_data(const T* data,
163 : const size_t fra_size,
164 : const size_t n_fra,
165 : const size_t n_fra_per_w,
166 : const size_t limit,
167 : const size_t max_frame,
168 : const uint8_t p,
169 : const uint8_t n_spaces,
170 : const bool hex)
171 : {
172 405 : constexpr bool is_float_type = std::is_same<float, T>::value || std::is_same<double, T>::value;
173 :
174 405 : std::ios::fmtflags f(std::cout.flags());
175 405 : if (hex)
176 : {
177 : if (is_float_type)
178 0 : std::cout << std::hexfloat << std::hex;
179 : else
180 0 : std::cout << std::hex;
181 : }
182 : else
183 405 : std::cout << std::fixed << std::setprecision(p) << std::dec;
184 :
185 405 : if (n_fra == 1 && max_frame != 0)
186 : {
187 5670 : for (size_t i = 0; i < limit; i++)
188 : {
189 5265 : if (hex)
190 0 : std::cout << (!is_float_type ? "0x" : "") << +data[i] << (i < limit - 1 ? ", " : "");
191 : else
192 5265 : std::cout << std::setw(p + 3) << +data[i] << (i < limit - 1 ? ", " : "");
193 : }
194 405 : std::cout << (limit < fra_size ? ", ..." : "");
195 405 : }
196 : else
197 : {
198 0 : std::string spaces = "#";
199 0 : for (uint8_t s = 0; s < n_spaces - 1; s++)
200 0 : spaces += " ";
201 :
202 0 : auto n_digits_dec = [](size_t f) -> size_t
203 : {
204 0 : size_t count = 0;
205 0 : while (f && ++count)
206 0 : f /= 10;
207 0 : return count;
208 : };
209 :
210 0 : const auto n_digits = n_digits_dec(max_frame);
211 0 : auto ftos = [&n_digits_dec, &n_digits](size_t f) -> std::string
212 : {
213 0 : auto n_zero = n_digits - n_digits_dec(f);
214 0 : std::string f_str = "";
215 0 : for (size_t z = 0; z < n_zero; z++)
216 0 : f_str += "0";
217 0 : f_str += std::to_string(f);
218 0 : return f_str;
219 0 : };
220 :
221 0 : const auto n_digits_w = n_digits_dec((max_frame / n_fra_per_w) == 0 ? 1 : (max_frame / n_fra_per_w));
222 0 : auto wtos = [&n_digits_dec, &n_digits_w](size_t w) -> std::string
223 : {
224 0 : auto n_zero = n_digits_w - n_digits_dec(w);
225 0 : std::string f_str = "";
226 0 : for (size_t z = 0; z < n_zero; z++)
227 0 : f_str += "0";
228 0 : f_str += std::to_string(w);
229 0 : return f_str;
230 0 : };
231 :
232 0 : for (size_t f = 0; f < max_frame; f++)
233 : {
234 0 : const auto w = f / n_fra_per_w;
235 0 : std::cout << (f >= 1 ? spaces : "") << rang::style::bold << rang::fg::gray << "f" << ftos(f + 1) << "_w"
236 0 : << wtos(w + 1) << rang::style::reset << "(";
237 :
238 0 : for (size_t i = 0; i < limit; i++)
239 : {
240 0 : if (hex)
241 0 : std::cout << (!is_float_type ? "0x" : "") << +data[f * fra_size + i] << (i < limit - 1 ? ", " : "");
242 : else
243 0 : std::cout << std::setw(p + 3) << +data[f * fra_size + i] << (i < limit - 1 ? ", " : "");
244 : }
245 0 : std::cout << (limit < fra_size ? ", ..." : "") << ")" << (f < n_fra - 1 ? ", \n" : "");
246 : }
247 :
248 0 : if (max_frame < n_fra)
249 : {
250 0 : const auto w1 = max_frame / n_fra_per_w;
251 0 : const auto w2 = n_fra / n_fra_per_w;
252 0 : std::cout << (max_frame >= 1 ? spaces : "") << rang::style::bold << rang::fg::gray << "f"
253 0 : << std::setw(n_digits) << max_frame + 1 << "_w" << std::setw(n_digits_w) << w1 + 1 << "->"
254 0 : << "f" << std::setw(n_digits) << n_fra << "_w" << std::setw(n_digits_w) << w2 + 1 << ":"
255 0 : << rang::style::reset << "(...)";
256 : }
257 0 : }
258 :
259 405 : std::cout.flags(f);
260 405 : }
261 :
262 : void
263 3181650 : Task::_exec(const int frame_id, const bool managed_memory)
264 : {
265 3181650 : const auto n_frames = this->get_module().get_n_frames();
266 3167559 : const auto n_frames_per_wave = this->get_module().get_n_frames_per_wave();
267 3130414 : const auto n_waves = this->get_module().get_n_waves();
268 3108076 : const auto n_frames_per_wave_rest = this->get_module().get_n_frames_per_wave_rest();
269 :
270 : // do not use 'this->status' because the dataptr can have been changed by the 'tools::Sequence' when using the no
271 : // copy mode
272 3092182 : int* status = this->sockets.back()->get_dataptr<int>();
273 7804053 : for (size_t w = 0; w < n_waves; w++)
274 4770056 : status[w] = (int)status_t::UNKNOWN;
275 :
276 3033997 : if ((managed_memory == false && frame_id >= 0) || (frame_id == -1 && n_frames_per_wave == n_frames) ||
277 163317 : (frame_id == 0 && n_frames_per_wave == 1) || (frame_id == 0 && n_waves > 1) ||
278 0 : (frame_id == 0 && n_frames_per_wave_rest == 0))
279 : {
280 2866664 : const auto real_frame_id = frame_id == -1 ? 0 : frame_id;
281 2866664 : const size_t w = (real_frame_id % n_frames) / n_frames_per_wave;
282 2866664 : status[w] = this->codelet(*this->module, *this, real_frame_id);
283 3103913 : }
284 : else
285 : {
286 : // save the initial dataptr of the sockets
287 468271 : for (size_t sid = 0; sid < this->sockets.size() - 1; sid++)
288 300376 : sockets_dataptr_init[sid] = (int8_t*)this->sockets[sid]->_get_dataptr();
289 :
290 163969 : if (frame_id > 0 && managed_memory == true && n_frames_per_wave > 1)
291 : {
292 0 : const size_t w = (frame_id % n_frames) / n_frames_per_wave;
293 0 : const size_t w_pos = frame_id % n_frames_per_wave;
294 :
295 0 : for (size_t sid = 0; sid < this->sockets.size() - 1; sid++)
296 : {
297 0 : if (sockets[sid]->get_type() == socket_t::SIN || sockets[sid]->get_type() == socket_t::SFWD)
298 0 : std::copy(
299 0 : sockets_dataptr_init[sid] + ((frame_id % n_frames) + 0) * sockets_databytes_per_frame[sid],
300 0 : sockets_dataptr_init[sid] + ((frame_id % n_frames) + 1) * sockets_databytes_per_frame[sid],
301 0 : sockets_data[sid].begin() + w_pos * sockets_databytes_per_frame[sid]);
302 0 : this->sockets[sid]->dataptr = (void*)sockets_data[sid].data();
303 : }
304 :
305 0 : status[w] = this->codelet(*this->module, *this, w * n_frames_per_wave);
306 :
307 0 : for (size_t sid = 0; sid < this->sockets.size() - 1; sid++)
308 0 : if (sockets[sid]->get_type() == socket_t::SOUT || sockets[sid]->get_type() == socket_t::SFWD)
309 0 : std::copy(sockets_data[sid].begin() + (w_pos + 0) * sockets_databytes_per_frame[sid],
310 0 : sockets_data[sid].begin() + (w_pos + 1) * sockets_databytes_per_frame[sid],
311 0 : sockets_dataptr_init[sid] + (frame_id % n_frames) * sockets_databytes_per_frame[sid]);
312 0 : }
313 : else // if (frame_id <= 0 || n_frames_per_wave == 1)
314 : {
315 163969 : const size_t w_start = (frame_id < 0) ? 0 : frame_id % n_waves;
316 163969 : const size_t w_stop = (frame_id < 0) ? n_waves : w_start + 1;
317 :
318 163969 : size_t w = 0;
319 163969 : auto exec_status = status_t::SUCCESS;
320 1831856 : for (w = w_start; w < w_stop - 1 && exec_status != status_t::FAILURE_STOP; w++)
321 : {
322 4744771 : for (size_t sid = 0; sid < this->sockets.size() - 1; sid++)
323 3041333 : this->sockets[sid]->dataptr =
324 6121140 : (void*)(sockets_dataptr_init[sid] + w * n_frames_per_wave * sockets_databytes_per_frame[sid]);
325 :
326 1600328 : status[w] = this->codelet(*this->module, *this, w * n_frames_per_wave);
327 1667887 : exec_status = (status_t)status[w];
328 : }
329 :
330 161094 : if (exec_status != status_t::FAILURE_STOP)
331 : {
332 164314 : if (n_frames_per_wave_rest == 0)
333 : {
334 465538 : for (size_t sid = 0; sid < this->sockets.size() - 1; sid++)
335 300377 : this->sockets[sid]->dataptr =
336 601701 : (void*)(sockets_dataptr_init[sid] + w * n_frames_per_wave * sockets_databytes_per_frame[sid]);
337 :
338 162994 : status[w] = this->codelet(*this->module, *this, w * n_frames_per_wave);
339 : }
340 : else
341 : {
342 0 : for (size_t sid = 0; sid < this->sockets.size() - 1; sid++)
343 : {
344 0 : if (sockets[sid]->get_type() == socket_t::SIN || sockets[sid]->get_type() == socket_t::SFWD)
345 0 : std::copy(sockets_dataptr_init[sid] +
346 0 : w * n_frames_per_wave * sockets_databytes_per_frame[sid],
347 0 : sockets_dataptr_init[sid] + n_frames * sockets_databytes_per_frame[sid],
348 0 : sockets_data[sid].begin());
349 0 : this->sockets[sid]->dataptr = (void*)sockets_data[sid].data();
350 : }
351 :
352 0 : status[w] = this->codelet(*this->module, *this, w * n_frames_per_wave);
353 :
354 0 : for (size_t sid = 0; sid < this->sockets.size() - 1; sid++)
355 0 : if (sockets[sid]->get_type() == socket_t::SOUT || sockets[sid]->get_type() == socket_t::SFWD)
356 0 : std::copy(
357 0 : sockets_data[sid].begin(),
358 0 : sockets_data[sid].begin() + n_frames_per_wave_rest * sockets_databytes_per_frame[sid],
359 0 : sockets_dataptr_init[sid] + w * n_frames_per_wave * sockets_databytes_per_frame[sid]);
360 : }
361 : }
362 : }
363 :
364 : // restore the initial dataptr of the sockets
365 464718 : for (size_t sid = 0; sid < this->sockets.size() - 1; sid++)
366 300694 : this->sockets[sid]->dataptr = (void*)sockets_dataptr_init[sid];
367 : }
368 3267157 : }
369 :
370 : const std::vector<int>&
371 3153700 : Task::exec(const int frame_id, const bool managed_memory)
372 : {
373 : #ifndef SPU_FAST
374 3153700 : if (this->is_fast() && !this->is_debug() && !this->is_stats())
375 : {
376 : #endif
377 3150401 : this->_exec(frame_id, managed_memory);
378 3252935 : this->n_calls++;
379 3252935 : return this->get_status();
380 : #ifndef SPU_FAST
381 : }
382 :
383 7582 : if (frame_id != -1 && (size_t)frame_id >= this->get_module().get_n_frames())
384 : {
385 0 : std::stringstream message;
386 0 : message << "'frame_id' has to be equal to '-1' or to be smaller than 'n_frames' ('frame_id' = " << frame_id
387 0 : << ", 'n_frames' = " << this->get_module().get_n_frames() << ").";
388 0 : throw tools::length_error(__FILE__, __LINE__, __func__, message.str());
389 0 : }
390 :
391 8732 : if (this->is_fast() || this->can_exec())
392 : {
393 8724 : size_t max_n_chars = 0;
394 8724 : if (this->is_debug())
395 : {
396 337 : auto n_fra = this->module->get_n_frames();
397 337 : auto n_fra_per_w = this->module->get_n_frames_per_wave();
398 :
399 : std::string module_name =
400 337 : module->get_custom_name().empty() ? module->get_name() : module->get_custom_name();
401 :
402 337 : std::cout << "# ";
403 337 : std::cout << rang::style::bold << rang::fg::green << module_name << rang::style::reset
404 337 : << "::" << rang::style::bold << rang::fg::magenta << get_name() << rang::style::reset << "(";
405 744 : for (auto i = 0; i < (int)sockets.size() - 1; i++)
406 : {
407 407 : auto& s = *sockets[i];
408 407 : auto s_type = s.get_type();
409 407 : auto n_elmts = s.get_databytes() / (size_t)s.get_datatype_size();
410 407 : std::cout << rang::style::bold << rang::fg::blue << (s_type == socket_t::SIN ? "const " : "")
411 407 : << s.get_datatype_string() << rang::style::reset << " " << s.get_name() << "["
412 814 : << (n_fra > 1 ? std::to_string(n_fra) + "x" : "") << (n_elmts / n_fra) << "]"
413 407 : << (i < (int)sockets.size() - 2 ? ", " : "");
414 :
415 407 : max_n_chars = std::max(s.get_name().size(), max_n_chars);
416 : }
417 337 : std::cout << ")" << std::endl;
418 :
419 1081 : for (auto& s : sockets)
420 : {
421 744 : auto s_type = s->get_type();
422 744 : if (s_type == socket_t::SIN || s_type == socket_t::SFWD)
423 : {
424 219 : std::string spaces;
425 347 : for (size_t ss = 0; ss < max_n_chars - s->get_name().size(); ss++)
426 128 : spaces += " ";
427 :
428 219 : auto n_elmts = s->get_databytes() / (size_t)s->get_datatype_size();
429 219 : auto fra_size = n_elmts / n_fra;
430 219 : auto limit = debug_limit != -1 ? std::min(fra_size, (size_t)debug_limit) : fra_size;
431 219 : auto max_frame = debug_frame_max != -1 ? std::min(n_fra, (size_t)debug_frame_max) : n_fra;
432 219 : auto p = debug_precision;
433 219 : auto h = debug_hex;
434 219 : std::cout << "# {IN} " << s->get_name() << spaces << " = [";
435 219 : if (s->get_datatype() == typeid(int8_t))
436 0 : display_data(s->get_dataptr<const int8_t>(),
437 : fra_size,
438 : n_fra,
439 : n_fra_per_w,
440 : limit,
441 : max_frame,
442 : p,
443 0 : (uint8_t)max_n_chars + 12,
444 : h);
445 219 : else if (s->get_datatype() == typeid(uint8_t))
446 174 : display_data(s->get_dataptr<const uint8_t>(),
447 : fra_size,
448 : n_fra,
449 : n_fra_per_w,
450 : limit,
451 : max_frame,
452 : p,
453 174 : (uint8_t)max_n_chars + 12,
454 : h);
455 45 : else if (s->get_datatype() == typeid(int16_t))
456 0 : display_data(s->get_dataptr<const int16_t>(),
457 : fra_size,
458 : n_fra,
459 : n_fra_per_w,
460 : limit,
461 : max_frame,
462 : p,
463 0 : (uint8_t)max_n_chars + 12,
464 : h);
465 45 : else if (s->get_datatype() == typeid(uint16_t))
466 0 : display_data(s->get_dataptr<const uint16_t>(),
467 : fra_size,
468 : n_fra,
469 : n_fra_per_w,
470 : limit,
471 : max_frame,
472 : p,
473 0 : (uint8_t)max_n_chars + 12,
474 : h);
475 45 : else if (s->get_datatype() == typeid(int32_t))
476 0 : display_data(s->get_dataptr<const int32_t>(),
477 : fra_size,
478 : n_fra,
479 : n_fra_per_w,
480 : limit,
481 : max_frame,
482 : p,
483 0 : (uint8_t)max_n_chars + 12,
484 : h);
485 45 : else if (s->get_datatype() == typeid(uint32_t))
486 27 : display_data(s->get_dataptr<const uint32_t>(),
487 : fra_size,
488 : n_fra,
489 : n_fra_per_w,
490 : limit,
491 : max_frame,
492 : p,
493 27 : (uint8_t)max_n_chars + 12,
494 : h);
495 18 : else if (s->get_datatype() == typeid(int64_t))
496 0 : display_data(s->get_dataptr<const int64_t>(),
497 : fra_size,
498 : n_fra,
499 : n_fra_per_w,
500 : limit,
501 : max_frame,
502 : p,
503 0 : (uint8_t)max_n_chars + 12,
504 : h);
505 18 : else if (s->get_datatype() == typeid(uint64_t))
506 18 : display_data(s->get_dataptr<const uint64_t>(),
507 : fra_size,
508 : n_fra,
509 : n_fra_per_w,
510 : limit,
511 : max_frame,
512 : p,
513 18 : (uint8_t)max_n_chars + 12,
514 : h);
515 0 : else if (s->get_datatype() == typeid(float))
516 0 : display_data(s->get_dataptr<const float>(),
517 : fra_size,
518 : n_fra,
519 : n_fra_per_w,
520 : limit,
521 : max_frame,
522 : p,
523 0 : (uint8_t)max_n_chars + 12,
524 : h);
525 0 : else if (s->get_datatype() == typeid(double))
526 0 : display_data(s->get_dataptr<const double>(),
527 : fra_size,
528 : n_fra,
529 : n_fra_per_w,
530 : limit,
531 : max_frame,
532 : p,
533 0 : (uint8_t)max_n_chars + 12,
534 : h);
535 219 : std::cout << "]" << std::endl;
536 219 : }
537 : }
538 337 : }
539 :
540 8720 : if (this->is_stats())
541 : {
542 8366 : auto t_start = std::chrono::steady_clock::now();
543 8379 : this->_exec(frame_id, managed_memory);
544 8260 : auto duration = std::chrono::steady_clock::now() - t_start;
545 :
546 8272 : this->duration_total += duration;
547 8257 : if (n_calls)
548 : {
549 7869 : this->duration_min = std::min(this->duration_min, duration);
550 7873 : this->duration_max = std::max(this->duration_max, duration);
551 : }
552 : else
553 : {
554 388 : this->duration_min = duration;
555 388 : this->duration_max = duration;
556 : }
557 : }
558 : else
559 : {
560 353 : this->_exec(frame_id, managed_memory);
561 : }
562 8626 : this->n_calls++;
563 :
564 8626 : if (this->is_debug())
565 : {
566 334 : auto n_fra = this->module->get_n_frames();
567 334 : auto n_fra_per_w = this->module->get_n_frames_per_wave();
568 1070 : for (auto& s : sockets)
569 : {
570 736 : auto s_type = s->get_type();
571 736 : if ((s_type == socket_t::SOUT) && s->get_name() != "status")
572 : {
573 186 : std::string spaces;
574 204 : for (size_t ss = 0; ss < max_n_chars - s->get_name().size(); ss++)
575 18 : spaces += " ";
576 :
577 186 : auto n_elmts = s->get_databytes() / (size_t)s->get_datatype_size();
578 186 : auto fra_size = n_elmts / n_fra;
579 186 : auto limit = debug_limit != -1 ? std::min(fra_size, (size_t)debug_limit) : fra_size;
580 186 : auto max_frame = debug_frame_max != -1 ? std::min(n_fra, (size_t)debug_frame_max) : n_fra;
581 186 : auto p = debug_precision;
582 186 : auto h = debug_hex;
583 186 : std::cout << "# {OUT} " << s->get_name() << spaces << " = [";
584 186 : if (s->get_datatype() == typeid(int8_t))
585 0 : display_data(s->get_dataptr<const int8_t>(),
586 : fra_size,
587 : n_fra,
588 : n_fra_per_w,
589 : limit,
590 : max_frame,
591 : p,
592 0 : (uint8_t)max_n_chars + 12,
593 : h);
594 186 : else if (s->get_datatype() == typeid(uint8_t))
595 150 : display_data(s->get_dataptr<const uint8_t>(),
596 : fra_size,
597 : n_fra,
598 : n_fra_per_w,
599 : limit,
600 : max_frame,
601 : p,
602 150 : (uint8_t)max_n_chars + 12,
603 : h);
604 36 : else if (s->get_datatype() == typeid(int16_t))
605 0 : display_data(s->get_dataptr<const int16_t>(),
606 : fra_size,
607 : n_fra,
608 : n_fra_per_w,
609 : limit,
610 : max_frame,
611 : p,
612 0 : (uint8_t)max_n_chars + 12,
613 : h);
614 36 : else if (s->get_datatype() == typeid(uint16_t))
615 0 : display_data(s->get_dataptr<const uint16_t>(),
616 : fra_size,
617 : n_fra,
618 : n_fra_per_w,
619 : limit,
620 : max_frame,
621 : p,
622 0 : (uint8_t)max_n_chars + 12,
623 : h);
624 36 : else if (s->get_datatype() == typeid(int32_t))
625 0 : display_data(s->get_dataptr<const int32_t>(),
626 : fra_size,
627 : n_fra,
628 : n_fra_per_w,
629 : limit,
630 : max_frame,
631 : p,
632 0 : (uint8_t)max_n_chars + 12,
633 : h);
634 36 : else if (s->get_datatype() == typeid(uint32_t))
635 18 : display_data(s->get_dataptr<const uint32_t>(),
636 : fra_size,
637 : n_fra,
638 : n_fra_per_w,
639 : limit,
640 : max_frame,
641 : p,
642 18 : (uint8_t)max_n_chars + 12,
643 : h);
644 18 : else if (s->get_datatype() == typeid(int64_t))
645 0 : display_data(s->get_dataptr<const int64_t>(),
646 : fra_size,
647 : n_fra,
648 : n_fra_per_w,
649 : limit,
650 : max_frame,
651 : p,
652 0 : (uint8_t)max_n_chars + 12,
653 : h);
654 18 : else if (s->get_datatype() == typeid(uint64_t))
655 18 : display_data(s->get_dataptr<const uint64_t>(),
656 : fra_size,
657 : n_fra,
658 : n_fra_per_w,
659 : limit,
660 : max_frame,
661 : p,
662 18 : (uint8_t)max_n_chars + 12,
663 : h);
664 0 : else if (s->get_datatype() == typeid(float))
665 0 : display_data(s->get_dataptr<const float>(),
666 : fra_size,
667 : n_fra,
668 : n_fra_per_w,
669 : limit,
670 : max_frame,
671 : p,
672 0 : (uint8_t)max_n_chars + 12,
673 : h);
674 0 : else if (s->get_datatype() == typeid(double))
675 0 : display_data(s->get_dataptr<const double>(),
676 : fra_size,
677 : n_fra,
678 : n_fra_per_w,
679 : limit,
680 : max_frame,
681 : p,
682 0 : (uint8_t)max_n_chars + 12,
683 : h);
684 186 : std::cout << "]" << std::endl;
685 186 : }
686 : }
687 334 : std::cout << "# Returned status: [";
688 : // do not use 'this->status' because the dataptr can have been changed by the 'tools::Sequence' when using
689 : // the no copy mode
690 334 : int* status = this->sockets.back()->get_dataptr<int>();
691 668 : for (size_t w = 0; w < this->get_module().get_n_waves(); w++)
692 : {
693 334 : if (status_t_to_string.count(status[w]))
694 334 : std::cout << ((w != 0) ? ", " : "") << std::dec << status[w] << " '"
695 334 : << status_t_to_string[status[w]] << "'";
696 : else
697 0 : std::cout << ((w != 0) ? ", " : "") << std::dec << status[w];
698 : }
699 334 : std::cout << "]" << std::endl;
700 334 : std::cout << "#" << std::noshowbase << std::endl;
701 : }
702 :
703 : // if (exec_status < 0)
704 : // {
705 : // std::stringstream message;
706 : // message << "'exec_status' can't be negative ('exec_status' = " << exec_status << ").";
707 : // throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
708 : // }
709 :
710 8622 : return this->get_status();
711 : }
712 : else
713 : {
714 0 : std::stringstream socs;
715 0 : socs << "'socket(s).name' = [";
716 0 : auto s = 0;
717 0 : for (size_t i = 0; i < sockets.size(); i++)
718 0 : if (sockets[i]->dataptr == nullptr) socs << (s != 0 ? ", " : "") << sockets[i]->name;
719 0 : socs << "]";
720 :
721 0 : std::stringstream message;
722 : message << "The task cannot be executed because some of the inputs/output sockets are not fed ('task.name' = "
723 0 : << this->get_name() << ", 'module.name' = " << module->get_name() << ", " << socs.str() << ").";
724 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
725 0 : }
726 : #endif /* !SPU_FAST */
727 : }
728 :
729 : template<typename T>
730 : Socket&
731 7630 : Task::create_2d_socket(const std::string& name,
732 : const size_t n_rows,
733 : const size_t n_cols,
734 : const socket_t type,
735 : const bool hack_status)
736 : {
737 7630 : if (name.empty())
738 : {
739 0 : std::stringstream message;
740 : message << "Impossible to create this socket because the name is empty ('task.name' = " << this->get_name()
741 0 : << ", 'module.name' = " << module->get_name() << ").";
742 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
743 0 : }
744 :
745 7630 : if (name == "status" && !hack_status)
746 : {
747 0 : std::stringstream message;
748 0 : message << "A socket can't be named 'status'.";
749 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
750 0 : }
751 :
752 14313 : for (auto& s : sockets)
753 6683 : if (s->get_name() == name)
754 : {
755 0 : std::stringstream message;
756 : message << "Impossible to create this socket because an other socket has the same name ('socket.name' = "
757 0 : << name << ", 'task.name' = " << this->get_name() << ", 'module.name' = " << module->get_name()
758 0 : << ").";
759 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
760 0 : }
761 :
762 14313 : for (auto s : this->sockets)
763 6683 : if (s->get_name() == "status")
764 : {
765 0 : std::stringstream message;
766 0 : message << "Creating new sockets after the 'status' socket is forbidden.";
767 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
768 0 : }
769 :
770 7630 : std::pair<size_t, size_t> databytes_per_dim = { n_rows, n_cols * sizeof(T) };
771 7630 : auto s = std::make_shared<Socket>(*this, name, typeid(T), databytes_per_dim, type, this->is_fast());
772 :
773 7630 : sockets.push_back(std::move(s));
774 :
775 7630 : this->sockets_dataptr_init.push_back(nullptr);
776 7630 : this->sockets_databytes_per_frame.push_back(sockets.back()->get_databytes() / this->get_module().get_n_frames());
777 7630 : this->sockets_data.push_back(
778 15260 : std::vector<int8_t>((this->get_module().get_n_frames_per_wave() > 1)
779 0 : ? this->sockets_databytes_per_frame.back() * this->get_module().get_n_frames_per_wave()
780 : : 0));
781 :
782 15260 : return *sockets.back();
783 7630 : }
784 :
785 : template<typename T>
786 : size_t
787 1862 : Task::create_2d_socket_in(const std::string& name, const size_t n_rows, const size_t n_cols)
788 : {
789 1862 : auto& s = create_2d_socket<T>(name, n_rows, n_cols, socket_t::SIN);
790 1862 : last_input_socket = &s;
791 :
792 1862 : this->n_input_sockets++;
793 :
794 1862 : return sockets.size() - 1;
795 : }
796 :
797 : size_t
798 611 : Task::create_2d_socket_in(const std::string& name,
799 : const size_t n_rows,
800 : const size_t n_cols,
801 : const std::type_index& datatype)
802 : {
803 611 : if (datatype == typeid(int8_t))
804 66 : return this->template create_2d_socket_in<int8_t>(name, n_rows, n_cols);
805 545 : else if (datatype == typeid(uint8_t))
806 418 : return this->template create_2d_socket_in<uint8_t>(name, n_rows, n_cols);
807 127 : else if (datatype == typeid(int16_t))
808 0 : return this->template create_2d_socket_in<int16_t>(name, n_rows, n_cols);
809 127 : else if (datatype == typeid(uint16_t))
810 0 : return this->template create_2d_socket_in<uint16_t>(name, n_rows, n_cols);
811 127 : else if (datatype == typeid(int32_t))
812 27 : return this->template create_2d_socket_in<int32_t>(name, n_rows, n_cols);
813 100 : else if (datatype == typeid(uint32_t))
814 84 : return this->template create_2d_socket_in<uint32_t>(name, n_rows, n_cols);
815 16 : else if (datatype == typeid(int64_t))
816 0 : return this->template create_2d_socket_in<int64_t>(name, n_rows, n_cols);
817 16 : else if (datatype == typeid(uint64_t))
818 16 : return this->template create_2d_socket_in<uint64_t>(name, n_rows, n_cols);
819 0 : else if (datatype == typeid(float))
820 0 : return this->template create_2d_socket_in<float>(name, n_rows, n_cols);
821 0 : else if (datatype == typeid(double))
822 0 : return this->template create_2d_socket_in<double>(name, n_rows, n_cols);
823 : else
824 : {
825 0 : std::stringstream message;
826 0 : message << "This should never happen.";
827 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
828 0 : }
829 : }
830 :
831 : size_t
832 0 : Task::create_2d_socket_in(const std::string& name, const size_t n_rows, const size_t n_cols, const datatype_t datatype)
833 : {
834 0 : switch (datatype)
835 : {
836 0 : case datatype_t::F64:
837 0 : return this->template create_2d_socket_in<double>(name, n_rows, n_cols);
838 : break;
839 0 : case datatype_t::F32:
840 0 : return this->template create_2d_socket_in<float>(name, n_rows, n_cols);
841 : break;
842 0 : case datatype_t::S64:
843 0 : return this->template create_2d_socket_in<int64_t>(name, n_rows, n_cols);
844 : break;
845 0 : case datatype_t::S32:
846 0 : return this->template create_2d_socket_in<int32_t>(name, n_rows, n_cols);
847 : break;
848 0 : case datatype_t::S16:
849 0 : return this->template create_2d_socket_in<int16_t>(name, n_rows, n_cols);
850 : break;
851 0 : case datatype_t::S8:
852 0 : return this->template create_2d_socket_in<int8_t>(name, n_rows, n_cols);
853 : break;
854 0 : case datatype_t::U64:
855 0 : return this->template create_2d_socket_in<uint64_t>(name, n_rows, n_cols);
856 : break;
857 0 : case datatype_t::U32:
858 0 : return this->template create_2d_socket_in<uint32_t>(name, n_rows, n_cols);
859 : break;
860 0 : case datatype_t::U16:
861 0 : return this->template create_2d_socket_in<uint16_t>(name, n_rows, n_cols);
862 : break;
863 0 : case datatype_t::U8:
864 0 : return this->template create_2d_socket_in<uint8_t>(name, n_rows, n_cols);
865 : break;
866 0 : default:
867 : {
868 0 : std::stringstream message;
869 0 : message << "This should never happen.";
870 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
871 : break;
872 0 : }
873 : }
874 : }
875 :
876 : template<typename T>
877 : size_t
878 4821 : Task::create_2d_socket_out(const std::string& name, const size_t n_rows, const size_t n_cols, const bool hack_status)
879 : {
880 4821 : auto& s = create_2d_socket<T>(name, n_rows, n_cols, socket_t::SOUT, hack_status);
881 4821 : this->n_output_sockets++;
882 :
883 : // memory allocation
884 4821 : if (is_autoalloc())
885 : {
886 4821 : out_buffers.push_back(buffer(s.get_databytes()));
887 4821 : s.dataptr = out_buffers.back().data(); // memory allocation
888 : }
889 :
890 4821 : return sockets.size() - 1;
891 : }
892 :
893 : size_t
894 606 : Task::create_2d_socket_out(const std::string& name,
895 : const size_t n_rows,
896 : const size_t n_cols,
897 : const std::type_index& datatype,
898 : const bool hack_status)
899 : {
900 606 : if (datatype == typeid(int8_t))
901 61 : return this->template create_2d_socket_out<int8_t>(name, n_rows, n_cols, hack_status);
902 545 : else if (datatype == typeid(uint8_t))
903 418 : return this->template create_2d_socket_out<uint8_t>(name, n_rows, n_cols, hack_status);
904 127 : else if (datatype == typeid(int16_t))
905 0 : return this->template create_2d_socket_out<int16_t>(name, n_rows, n_cols, hack_status);
906 127 : else if (datatype == typeid(uint16_t))
907 0 : return this->template create_2d_socket_out<uint16_t>(name, n_rows, n_cols, hack_status);
908 127 : else if (datatype == typeid(int32_t))
909 27 : return this->template create_2d_socket_out<int32_t>(name, n_rows, n_cols, hack_status);
910 100 : else if (datatype == typeid(uint32_t))
911 84 : return this->template create_2d_socket_out<uint32_t>(name, n_rows, n_cols, hack_status);
912 16 : else if (datatype == typeid(int64_t))
913 0 : return this->template create_2d_socket_out<int64_t>(name, n_rows, n_cols, hack_status);
914 16 : else if (datatype == typeid(uint64_t))
915 16 : return this->template create_2d_socket_out<uint64_t>(name, n_rows, n_cols, hack_status);
916 0 : else if (datatype == typeid(float))
917 0 : return this->template create_2d_socket_out<float>(name, n_rows, n_cols, hack_status);
918 0 : else if (datatype == typeid(double))
919 0 : return this->template create_2d_socket_out<double>(name, n_rows, n_cols, hack_status);
920 : else
921 : {
922 0 : std::stringstream message;
923 0 : message << "This should never happen.";
924 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
925 0 : }
926 : }
927 :
928 : size_t
929 0 : Task::create_2d_socket_out(const std::string& name,
930 : const size_t n_rows,
931 : const size_t n_cols,
932 : const datatype_t datatype,
933 : const bool hack_status)
934 : {
935 0 : switch (datatype)
936 : {
937 0 : case datatype_t::F64:
938 0 : return this->template create_2d_socket_out<double>(name, n_rows, n_cols, hack_status);
939 : break;
940 0 : case datatype_t::F32:
941 0 : return this->template create_2d_socket_out<float>(name, n_rows, n_cols, hack_status);
942 : break;
943 0 : case datatype_t::S64:
944 0 : return this->template create_2d_socket_out<int64_t>(name, n_rows, n_cols, hack_status);
945 : break;
946 0 : case datatype_t::S32:
947 0 : return this->template create_2d_socket_out<int32_t>(name, n_rows, n_cols, hack_status);
948 : break;
949 0 : case datatype_t::S16:
950 0 : return this->template create_2d_socket_out<int16_t>(name, n_rows, n_cols, hack_status);
951 : break;
952 0 : case datatype_t::S8:
953 0 : return this->template create_2d_socket_out<int8_t>(name, n_rows, n_cols, hack_status);
954 : break;
955 0 : case datatype_t::U64:
956 0 : return this->template create_2d_socket_out<uint64_t>(name, n_rows, n_cols, hack_status);
957 : break;
958 0 : case datatype_t::U32:
959 0 : return this->template create_2d_socket_out<uint32_t>(name, n_rows, n_cols, hack_status);
960 : break;
961 0 : case datatype_t::U16:
962 0 : return this->template create_2d_socket_out<uint16_t>(name, n_rows, n_cols, hack_status);
963 : break;
964 0 : case datatype_t::U8:
965 0 : return this->template create_2d_socket_out<uint8_t>(name, n_rows, n_cols, hack_status);
966 : break;
967 0 : default:
968 : {
969 0 : std::stringstream message;
970 0 : message << "This should never happen.";
971 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
972 : break;
973 0 : }
974 : }
975 : }
976 :
977 : template<typename T>
978 : size_t
979 947 : Task::create_2d_socket_fwd(const std::string& name, const size_t n_rows, const size_t n_cols)
980 : {
981 947 : auto& s = create_2d_socket<T>(name, n_rows, n_cols, socket_t::SFWD);
982 947 : last_input_socket = &s;
983 :
984 947 : this->n_fwd_sockets++;
985 :
986 947 : return sockets.size() - 1;
987 : }
988 :
989 : size_t
990 0 : Task::create_2d_socket_fwd(const std::string& name,
991 : const size_t n_rows,
992 : const size_t n_cols,
993 : const std::type_index& datatype)
994 : {
995 0 : if (datatype == typeid(int8_t))
996 0 : return this->template create_2d_socket_fwd<int8_t>(name, n_rows, n_cols);
997 0 : else if (datatype == typeid(uint8_t))
998 0 : return this->template create_2d_socket_fwd<uint8_t>(name, n_rows, n_cols);
999 0 : else if (datatype == typeid(int16_t))
1000 0 : return this->template create_2d_socket_fwd<int16_t>(name, n_rows, n_cols);
1001 0 : else if (datatype == typeid(uint16_t))
1002 0 : return this->template create_2d_socket_fwd<uint16_t>(name, n_rows, n_cols);
1003 0 : else if (datatype == typeid(int32_t))
1004 0 : return this->template create_2d_socket_fwd<int32_t>(name, n_rows, n_cols);
1005 0 : else if (datatype == typeid(uint32_t))
1006 0 : return this->template create_2d_socket_fwd<uint32_t>(name, n_rows, n_cols);
1007 0 : else if (datatype == typeid(int64_t))
1008 0 : return this->template create_2d_socket_fwd<int64_t>(name, n_rows, n_cols);
1009 0 : else if (datatype == typeid(uint64_t))
1010 0 : return this->template create_2d_socket_fwd<uint64_t>(name, n_rows, n_cols);
1011 0 : else if (datatype == typeid(float))
1012 0 : return this->template create_2d_socket_fwd<float>(name, n_rows, n_cols);
1013 0 : else if (datatype == typeid(double))
1014 0 : return this->template create_2d_socket_fwd<double>(name, n_rows, n_cols);
1015 : else
1016 : {
1017 0 : std::stringstream message;
1018 0 : message << "This should never happen.";
1019 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
1020 0 : }
1021 : }
1022 :
1023 : size_t
1024 0 : Task::create_2d_socket_fwd(const std::string& name, const size_t n_rows, const size_t n_cols, const datatype_t datatype)
1025 : {
1026 0 : switch (datatype)
1027 : {
1028 0 : case datatype_t::F64:
1029 0 : return this->template create_2d_socket_fwd<double>(name, n_rows, n_cols);
1030 : break;
1031 0 : case datatype_t::F32:
1032 0 : return this->template create_2d_socket_fwd<float>(name, n_rows, n_cols);
1033 : break;
1034 0 : case datatype_t::S64:
1035 0 : return this->template create_2d_socket_fwd<int64_t>(name, n_rows, n_cols);
1036 : break;
1037 0 : case datatype_t::S32:
1038 0 : return this->template create_2d_socket_fwd<int32_t>(name, n_rows, n_cols);
1039 : break;
1040 0 : case datatype_t::S16:
1041 0 : return this->template create_2d_socket_fwd<int16_t>(name, n_rows, n_cols);
1042 : break;
1043 0 : case datatype_t::S8:
1044 0 : return this->template create_2d_socket_fwd<int8_t>(name, n_rows, n_cols);
1045 : break;
1046 0 : case datatype_t::U64:
1047 0 : return this->template create_2d_socket_fwd<uint64_t>(name, n_rows, n_cols);
1048 : break;
1049 0 : case datatype_t::U32:
1050 0 : return this->template create_2d_socket_fwd<uint32_t>(name, n_rows, n_cols);
1051 : break;
1052 0 : case datatype_t::U16:
1053 0 : return this->template create_2d_socket_fwd<uint16_t>(name, n_rows, n_cols);
1054 : break;
1055 0 : case datatype_t::U8:
1056 0 : return this->template create_2d_socket_fwd<uint8_t>(name, n_rows, n_cols);
1057 : break;
1058 0 : default:
1059 : {
1060 0 : std::stringstream message;
1061 0 : message << "This should never happen.";
1062 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
1063 : break;
1064 0 : }
1065 : }
1066 : }
1067 :
1068 : void
1069 3071 : Task::create_codelet(std::function<int(module::Module& m, Task& t, const size_t frame_id)>& codelet)
1070 : {
1071 3071 : this->codelet = codelet;
1072 :
1073 : // create automatically a socket that contains the status of the task
1074 3071 : const bool hack_status = true;
1075 3071 : auto s = this->template create_2d_socket_out<int>("status", 1, this->get_module().get_n_waves(), hack_status);
1076 3071 : this->sockets[s]->dataptr = (void*)this->status.data();
1077 3071 : }
1078 :
1079 : void
1080 79568 : Task::update_n_frames(const size_t old_n_frames, const size_t new_n_frames)
1081 : {
1082 79568 : size_t sout_id = 0;
1083 285210 : for (auto& s : this->sockets)
1084 : {
1085 205642 : if (s->get_name() == "status")
1086 : {
1087 79568 : if (this->get_module().get_n_waves() * sizeof(int) != s->get_databytes())
1088 : {
1089 70452 : s->set_databytes(this->get_module().get_n_waves() * sizeof(int));
1090 70452 : this->status.resize(this->get_module().get_n_waves());
1091 70452 : s->set_dataptr((void*)this->status.data());
1092 : }
1093 : }
1094 : else
1095 : {
1096 126074 : const auto old_databytes = s->get_databytes();
1097 126074 : const auto new_databytes = (old_databytes / old_n_frames) * new_n_frames;
1098 126074 : s->set_databytes(new_databytes);
1099 :
1100 126074 : const size_t prev_n_rows_wo_nfra = s->get_n_rows() / old_n_frames;
1101 126074 : s->set_n_rows(prev_n_rows_wo_nfra * new_n_frames);
1102 :
1103 126074 : if (this->is_autoalloc() && s->get_type() == socket_t::SOUT)
1104 : {
1105 49836 : this->out_buffers[sout_id].resize(new_databytes);
1106 49836 : s->set_dataptr((void*)this->out_buffers[sout_id].data());
1107 49836 : sout_id++;
1108 : }
1109 : }
1110 : }
1111 79568 : }
1112 :
1113 : void
1114 18232 : Task::update_n_frames_per_wave(const size_t old_n_frames_per_wave, const size_t new_n_frames_per_wave)
1115 : {
1116 18232 : size_t s_id = 0;
1117 74452 : for (auto& s : this->sockets)
1118 : {
1119 56220 : if (s->get_name() == "status")
1120 : {
1121 18232 : if (this->get_module().get_n_waves() * sizeof(int) != s->get_databytes())
1122 : {
1123 9116 : s->set_databytes(this->get_module().get_n_waves() * sizeof(int));
1124 9116 : this->status.resize(this->get_module().get_n_waves());
1125 9116 : s->set_dataptr((void*)this->status.data());
1126 : }
1127 : }
1128 : else
1129 : {
1130 56982 : this->sockets_data[s_id].resize(
1131 18994 : (new_n_frames_per_wave > 1) ? this->sockets_databytes_per_frame[s_id] * new_n_frames_per_wave : 0);
1132 : }
1133 56220 : s_id++;
1134 : }
1135 18232 : }
1136 :
1137 : bool
1138 363 : Task::can_exec() const
1139 : {
1140 1417 : for (size_t i = 0; i < sockets.size(); i++)
1141 1049 : if (sockets[i]->dataptr == nullptr) return false;
1142 352 : return true;
1143 : }
1144 :
1145 : std::chrono::nanoseconds
1146 7778 : Task::get_duration_total() const
1147 : {
1148 7778 : return this->duration_total;
1149 : }
1150 :
1151 : std::chrono::nanoseconds
1152 1131 : Task::get_duration_avg() const
1153 : {
1154 1131 : return this->duration_total / this->n_calls;
1155 : }
1156 :
1157 : std::chrono::nanoseconds
1158 1042 : Task::get_duration_min() const
1159 : {
1160 1042 : return this->duration_min;
1161 : }
1162 :
1163 : std::chrono::nanoseconds
1164 1042 : Task::get_duration_max() const
1165 : {
1166 1042 : return this->duration_max;
1167 : }
1168 :
1169 : const std::vector<std::string>&
1170 272 : Task::get_timers_name() const
1171 : {
1172 272 : return this->timers_name;
1173 : }
1174 :
1175 : const std::vector<uint32_t>&
1176 0 : Task::get_timers_n_calls() const
1177 : {
1178 0 : return this->timers_n_calls;
1179 : }
1180 :
1181 : const std::vector<std::chrono::nanoseconds>&
1182 0 : Task::get_timers_total() const
1183 : {
1184 0 : return this->timers_total;
1185 : }
1186 :
1187 : const std::vector<std::chrono::nanoseconds>&
1188 0 : Task::get_timers_min() const
1189 : {
1190 0 : return this->timers_min;
1191 : }
1192 :
1193 : const std::vector<std::chrono::nanoseconds>&
1194 0 : Task::get_timers_max() const
1195 : {
1196 0 : return this->timers_max;
1197 : }
1198 :
1199 : size_t
1200 2435 : Task::get_n_input_sockets() const
1201 : {
1202 2435 : return this->n_input_sockets;
1203 : }
1204 :
1205 : size_t
1206 0 : Task::get_n_output_sockets() const
1207 : {
1208 0 : return this->n_output_sockets;
1209 : }
1210 :
1211 : size_t
1212 3584 : Task::get_n_fwd_sockets() const
1213 : {
1214 3584 : return this->n_fwd_sockets;
1215 : }
1216 :
1217 : void
1218 0 : Task::register_timer(const std::string& name)
1219 : {
1220 0 : this->timers_name.push_back(name);
1221 0 : this->timers_n_calls.push_back(0);
1222 0 : this->timers_total.push_back(std::chrono::nanoseconds(0));
1223 0 : this->timers_max.push_back(std::chrono::nanoseconds(0));
1224 0 : this->timers_min.push_back(std::chrono::nanoseconds(0));
1225 0 : }
1226 :
1227 : void
1228 72284 : Task::reset()
1229 : {
1230 72284 : this->n_calls = 0;
1231 72284 : this->duration_total = std::chrono::nanoseconds(0);
1232 72284 : this->duration_min = std::chrono::nanoseconds(0);
1233 72284 : this->duration_max = std::chrono::nanoseconds(0);
1234 :
1235 72284 : for (auto& x : this->timers_n_calls)
1236 0 : x = 0;
1237 72284 : for (auto& x : this->timers_total)
1238 0 : x = std::chrono::nanoseconds(0);
1239 72284 : for (auto& x : this->timers_min)
1240 0 : x = std::chrono::nanoseconds(0);
1241 72284 : for (auto& x : this->timers_max)
1242 0 : x = std::chrono::nanoseconds(0);
1243 72284 : }
1244 :
1245 : Task*
1246 66979 : Task::clone() const
1247 : {
1248 66979 : Task* t = new Task(*this);
1249 66979 : t->sockets.clear();
1250 66979 : t->last_input_socket = nullptr;
1251 66979 : t->fake_input_sockets.clear();
1252 :
1253 66979 : size_t out_buffers_counter = 0;
1254 241929 : for (auto s : this->sockets)
1255 : {
1256 174950 : void* dataptr = nullptr;
1257 174950 : if (s->get_type() == socket_t::SOUT && this->is_autoalloc())
1258 : {
1259 109939 : if (s->get_name() == "status")
1260 : {
1261 66979 : dataptr = (void*)t->status.data();
1262 66979 : out_buffers_counter++;
1263 : }
1264 : else
1265 42960 : dataptr = (void*)t->out_buffers[out_buffers_counter++].data();
1266 : }
1267 65011 : else if (s->get_type() == socket_t::SIN || s->get_type() == socket_t::SFWD)
1268 65011 : dataptr = s->_get_dataptr();
1269 :
1270 174950 : const std::pair<size_t, size_t> databytes_per_dim = { s->get_n_rows(), s->get_databytes() / s->get_n_rows() };
1271 : auto s_new = std::shared_ptr<Socket>(
1272 174950 : new Socket(*t, s->get_name(), s->get_datatype(), databytes_per_dim, s->get_type(), s->is_fast(), dataptr));
1273 174950 : t->sockets.push_back(s_new);
1274 :
1275 174950 : if (s_new->get_type() == socket_t::SIN || s_new->get_type() == socket_t::SFWD)
1276 65011 : t->last_input_socket = s_new.get();
1277 174950 : }
1278 :
1279 66979 : return t;
1280 : }
1281 :
1282 : void
1283 9240 : Task::_bind(Socket& s_out, const int priority)
1284 : {
1285 : // check if the 's_out' socket is already used for an other fake input socket
1286 9240 : bool already_bound = false;
1287 9240 : for (auto& fsi : this->fake_input_sockets)
1288 0 : if (&fsi->get_bound_socket() == &s_out)
1289 : {
1290 0 : already_bound = true;
1291 0 : break;
1292 : }
1293 :
1294 : // check if the 's_out' socket is already used for an other read input/fwd socket
1295 9240 : if (!already_bound)
1296 28130 : for (auto& s : this->sockets)
1297 18890 : if (s->get_type() == socket_t::SIN || s->get_type() == socket_t::SFWD)
1298 : {
1299 : try // because 's->get_bound_socket()' can throw if s->bound_socket == 'nullptr'
1300 : {
1301 1547 : if (&s->get_bound_socket() == &s_out)
1302 : {
1303 0 : already_bound = true;
1304 0 : break;
1305 : }
1306 : }
1307 692 : catch (...)
1308 : {
1309 692 : }
1310 : }
1311 :
1312 : // if the s_out socket is not already bound, then create a new fake input socket
1313 9240 : if (!already_bound)
1314 : {
1315 9240 : this->fake_input_sockets.push_back(
1316 18480 : std::shared_ptr<Socket>(new Socket(*this,
1317 18480 : "fake" + std::to_string(this->fake_input_sockets.size()),
1318 9240 : s_out.get_datatype(),
1319 9240 : s_out.get_databytes(),
1320 : socket_t::SIN,
1321 9240 : this->is_fast())));
1322 9240 : this->fake_input_sockets.back()->_bind(s_out, priority);
1323 9240 : this->last_input_socket = this->fake_input_sockets.back().get();
1324 9240 : this->n_input_sockets++;
1325 : }
1326 9240 : }
1327 :
1328 : void
1329 0 : Task::bind(Socket& s_out, const int priority)
1330 : {
1331 : #ifdef SPU_SHOW_DEPRECATED
1332 : std::clog << rang::tag::warning << "Deprecated: 'Task::bind()' should be replaced by 'Task::operator='."
1333 : << std::endl;
1334 : #ifdef SPU_STACKTRACE
1335 : #ifdef SPU_COLORS
1336 : bool enable_color = true;
1337 : #else
1338 : bool enable_color = false;
1339 : #endif
1340 : cpptrace::generate_trace().print(std::clog, enable_color);
1341 : #endif
1342 : #endif
1343 0 : this->_bind(s_out, priority);
1344 0 : }
1345 :
1346 : void
1347 0 : Task::_bind(Task& t_out, const int priority)
1348 : {
1349 0 : this->_bind(*t_out.sockets.back(), priority);
1350 0 : }
1351 :
1352 : void
1353 0 : Task::bind(Task& t_out, const int priority)
1354 : {
1355 : #ifdef SPU_SHOW_DEPRECATED
1356 : std::clog << rang::tag::warning << "Deprecated: 'Task::bind()' should be replaced by 'Task::operator='."
1357 : << std::endl;
1358 : #ifdef SPU_STACKTRACE
1359 : #ifdef SPU_COLORS
1360 : bool enable_color = true;
1361 : #else
1362 : bool enable_color = false;
1363 : #endif
1364 : cpptrace::generate_trace().print(std::clog, enable_color);
1365 : #endif
1366 : #endif
1367 0 : this->_bind(t_out, priority);
1368 0 : }
1369 :
1370 : void
1371 7377 : Task::operator=(Socket& s_out)
1372 : {
1373 : #ifndef SPU_FAST
1374 7377 : if (s_out.get_type() == socket_t::SOUT || s_out.get_type() == socket_t::SFWD)
1375 : #endif
1376 7377 : this->_bind(s_out);
1377 : #ifndef SPU_FAST
1378 : else
1379 : {
1380 0 : std::stringstream message;
1381 : message << "'s_out' should be and output socket ("
1382 0 : << "'s_out.datatype' = " << type_to_string[s_out.get_datatype()] << ", "
1383 0 : << "'s_out.name' = " << s_out.get_name() << ", "
1384 0 : << "'s_out.task.name' = " << s_out.task.get_name() << ", "
1385 0 : << "'s_out.type' = " << (s_out.get_type() == socket_t::SIN ? "SIN" : "SOUT") << ", "
1386 0 : << "'s_out.task.module.name' = " << s_out.task.get_module().get_custom_name() << ").";
1387 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
1388 0 : }
1389 : #endif
1390 7377 : }
1391 :
1392 : void
1393 300 : Task::operator=(Task& t_out)
1394 : {
1395 300 : (*this) = *t_out.sockets.back();
1396 300 : }
1397 :
1398 : size_t
1399 50457 : Task::unbind(Socket& s_out)
1400 : {
1401 50457 : if (this->fake_input_sockets.size())
1402 : {
1403 6277 : size_t i = 0;
1404 6317 : for (auto& fsi : this->fake_input_sockets)
1405 : {
1406 6277 : if (&fsi->get_bound_socket() == &s_out)
1407 : {
1408 6237 : const auto pos = fsi->unbind(s_out);
1409 6237 : if (this->last_input_socket == fsi.get()) this->last_input_socket = nullptr;
1410 6237 : this->fake_input_sockets.erase(this->fake_input_sockets.begin() + i);
1411 6237 : this->n_input_sockets--;
1412 6237 : if (this->fake_input_sockets.size() && this->last_input_socket == nullptr)
1413 0 : this->last_input_socket = this->fake_input_sockets.back().get();
1414 6237 : return pos;
1415 : }
1416 40 : i++;
1417 : }
1418 :
1419 40 : std::stringstream message;
1420 : message << "'s_out' is not bound the this task ("
1421 80 : << "'s_out.datatype' = " << type_to_string[s_out.datatype] << ", "
1422 40 : << "'s_out.name' = " << s_out.get_name() << ", "
1423 0 : << "'s_out.task.name' = " << s_out.task.get_name() << ", "
1424 40 : << "'s_out.task.module.name' = " << s_out.task.get_module().get_custom_name() << ", "
1425 40 : << "'task.name' = " << this->get_name() << ", "
1426 80 : << "'task.module.name' = " << this->get_module().get_custom_name() << ").";
1427 40 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
1428 40 : }
1429 : else
1430 : {
1431 44180 : std::stringstream message;
1432 : message << "This task does not have fake input socket to unbind ("
1433 88360 : << "'s_out.datatype' = " << type_to_string[s_out.datatype] << ", "
1434 44180 : << "'s_out.name' = " << s_out.get_name() << ", "
1435 0 : << "'s_out.task.name' = " << s_out.task.get_name() << ", "
1436 44180 : << "'s_out.task.module.name' = " << s_out.task.get_module().get_custom_name() << ", "
1437 44180 : << "'task.name' = " << this->get_name() << ", "
1438 88360 : << "'task.module.name' = " << this->get_module().get_custom_name() << ").";
1439 44180 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
1440 44180 : }
1441 : }
1442 :
1443 : size_t
1444 244 : Task::unbind(Task& t_out)
1445 : {
1446 244 : return this->unbind(*t_out.sockets.back());
1447 : }
1448 :
1449 : size_t
1450 2379 : Task::get_n_static_input_sockets() const
1451 : {
1452 2379 : size_t n = 0;
1453 8730 : for (auto& s : this->sockets)
1454 6351 : if (s->get_type() == socket_t::SIN && s->_get_dataptr() != nullptr && s->bound_socket == nullptr) n++;
1455 2379 : return n;
1456 : }
1457 :
1458 : bool
1459 0 : Task::is_stateless() const
1460 : {
1461 0 : return this->get_module().is_stateless();
1462 : }
1463 :
1464 : bool
1465 0 : Task::is_stateful() const
1466 : {
1467 0 : return this->get_module().is_stateful();
1468 : }
1469 :
1470 : bool
1471 1735 : Task::is_replicable() const
1472 : {
1473 1735 : return this->replicable;
1474 : }
1475 :
1476 : void
1477 270 : Task::set_replicability(const bool replicable)
1478 : {
1479 270 : if (replicable && !this->module->is_clonable())
1480 : {
1481 0 : std::stringstream message;
1482 : message << "The replicability of this task cannot be set to true because its corresponding module is not "
1483 0 : << "clonable (task.name = '" << this->get_name() << "', module.name = '"
1484 0 : << this->get_module().get_name() << "').";
1485 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
1486 0 : }
1487 270 : this->replicable = replicable;
1488 : // this->replicable = replicable ? this->module->is_clonable() : false;
1489 270 : }
1490 :
1491 : // ==================================================================================== explicit template instantiation
1492 : template size_t
1493 : Task::create_2d_socket_in<int8_t>(const std::string&, const size_t, const size_t);
1494 : template size_t
1495 : Task::create_2d_socket_in<uint8_t>(const std::string&, const size_t, const size_t);
1496 : template size_t
1497 : Task::create_2d_socket_in<int16_t>(const std::string&, const size_t, const size_t);
1498 : template size_t
1499 : Task::create_2d_socket_in<uint16_t>(const std::string&, const size_t, const size_t);
1500 : template size_t
1501 : Task::create_2d_socket_in<int32_t>(const std::string&, const size_t, const size_t);
1502 : template size_t
1503 : Task::create_2d_socket_in<uint32_t>(const std::string&, const size_t, const size_t);
1504 : template size_t
1505 : Task::create_2d_socket_in<int64_t>(const std::string&, const size_t, const size_t);
1506 : template size_t
1507 : Task::create_2d_socket_in<uint64_t>(const std::string&, const size_t, const size_t);
1508 : template size_t
1509 : Task::create_2d_socket_in<float>(const std::string&, const size_t, const size_t);
1510 : template size_t
1511 : Task::create_2d_socket_in<double>(const std::string&, const size_t, const size_t);
1512 :
1513 : template size_t
1514 : Task::create_2d_socket_out<int8_t>(const std::string&, const size_t, const size_t, const bool);
1515 : template size_t
1516 : Task::create_2d_socket_out<uint8_t>(const std::string&, const size_t, const size_t, const bool);
1517 : template size_t
1518 : Task::create_2d_socket_out<int16_t>(const std::string&, const size_t, const size_t, const bool);
1519 : template size_t
1520 : Task::create_2d_socket_out<uint16_t>(const std::string&, const size_t, const size_t, const bool);
1521 : template size_t
1522 : Task::create_2d_socket_out<int32_t>(const std::string&, const size_t, const size_t, const bool);
1523 : template size_t
1524 : Task::create_2d_socket_out<uint32_t>(const std::string&, const size_t, const size_t, const bool);
1525 : template size_t
1526 : Task::create_2d_socket_out<int64_t>(const std::string&, const size_t, const size_t, const bool);
1527 : template size_t
1528 : Task::create_2d_socket_out<uint64_t>(const std::string&, const size_t, const size_t, const bool);
1529 : template size_t
1530 : Task::create_2d_socket_out<float>(const std::string&, const size_t, const size_t, const bool);
1531 : template size_t
1532 : Task::create_2d_socket_out<double>(const std::string&, const size_t, const size_t, const bool);
1533 :
1534 : template size_t
1535 : Task::create_2d_socket_fwd<int8_t>(const std::string&, const size_t, const size_t);
1536 : template size_t
1537 : Task::create_2d_socket_fwd<uint8_t>(const std::string&, const size_t, const size_t);
1538 : template size_t
1539 : Task::create_2d_socket_fwd<int16_t>(const std::string&, const size_t, const size_t);
1540 : template size_t
1541 : Task::create_2d_socket_fwd<uint16_t>(const std::string&, const size_t, const size_t);
1542 : template size_t
1543 : Task::create_2d_socket_fwd<int32_t>(const std::string&, const size_t, const size_t);
1544 : template size_t
1545 : Task::create_2d_socket_fwd<uint32_t>(const std::string&, const size_t, const size_t);
1546 : template size_t
1547 : Task::create_2d_socket_fwd<int64_t>(const std::string&, const size_t, const size_t);
1548 : template size_t
1549 : Task::create_2d_socket_fwd<uint64_t>(const std::string&, const size_t, const size_t);
1550 : template size_t
1551 : Task::create_2d_socket_fwd<float>(const std::string&, const size_t, const size_t);
1552 : template size_t
1553 : Task::create_2d_socket_fwd<double>(const std::string&, const size_t, const size_t);
1554 : // ==================================================================================== explicit template instantiation
|