Line data Source code
1 : #include <cmath>
2 : #include <fstream>
3 : #include <iostream>
4 : #include <limits>
5 : #include <regex>
6 : #include <sstream>
7 :
8 : #include "Scheduler/From_file/Scheduler_from_file.hpp"
9 : #include "Tools/Exception/exception.hpp"
10 : #include "Tools/Thread/Thread_pinning/Thread_pinning_utils.hpp"
11 :
12 : using json = nlohmann::json;
13 :
14 : using namespace spu;
15 : using namespace spu::sched;
16 :
17 0 : Scheduler_from_file::Scheduler_from_file(runtime::Sequence& sequence, const std::string filename, uint8_t file_version)
18 : : Scheduler(sequence)
19 0 : , file_version(file_version)
20 : {
21 0 : std::ifstream f(filename);
22 0 : if (!f.good())
23 : {
24 0 : std::stringstream message;
25 0 : message << "The current file cannot be opened ('filename' = " << filename << ").";
26 0 : throw tools::invalid_argument(__FILE__, __LINE__, __func__, message.str());
27 0 : }
28 :
29 0 : json data = json::parse(f);
30 :
31 0 : if (file_version == 1)
32 : {
33 0 : this->contsruct_policy_v1(data, sequence);
34 : }
35 0 : else if (file_version == 2)
36 : {
37 0 : this->contsruct_policy_v2(data, sequence);
38 : }
39 : else
40 : {
41 0 : std::stringstream message;
42 0 : message << "Unsupported file version: " << static_cast<int>(file_version) << ". Supported version are 1 or 2.";
43 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
44 0 : }
45 0 : }
46 :
47 0 : Scheduler_from_file::Scheduler_from_file(runtime::Sequence* sequence, const std::string filename, uint8_t file_version)
48 0 : : Scheduler_from_file(*sequence, filename, file_version)
49 : {
50 0 : }
51 :
52 : // Construct policy function for V1 file
53 : void
54 0 : Scheduler_from_file::contsruct_policy_v1(json& data, runtime::Sequence& sequence)
55 : {
56 0 : if (!data.contains("schedule"))
57 : {
58 0 : std::stringstream message;
59 0 : message << "The current json file does not contain the required 'schedule' field.";
60 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
61 0 : }
62 :
63 0 : auto sched_data = data["schedule"];
64 :
65 0 : if (!sched_data.is_array())
66 : {
67 0 : std::stringstream message;
68 0 : message << "Unexpected type for the 'schedule' field (should be an array).";
69 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
70 0 : }
71 :
72 0 : this->sync_buff_sizes_from_file.resize(sched_data.size() - 1, 1);
73 0 : this->sync_active_waitings_from_file.resize(sched_data.size() - 1, false);
74 :
75 0 : size_t n_tasks_json = 0;
76 0 : for (size_t d = 0; d < sched_data.size(); d++)
77 : {
78 0 : if (!sched_data[d].contains("cores"))
79 : {
80 0 : std::stringstream message;
81 0 : message << "The current entry does not contain the 'cores' field.";
82 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
83 0 : }
84 0 : if (!sched_data[d].contains("tasks"))
85 : {
86 0 : std::stringstream message;
87 0 : message << "The current entry does not contain the 'tasks' field.";
88 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
89 0 : }
90 :
91 : size_t r;
92 0 : if (sched_data[d]["cores"].is_array())
93 : {
94 0 : if (!this->puids_from_file.size()) this->puids_from_file.resize(sched_data.size());
95 :
96 0 : this->puids_from_file[d].resize(sched_data[d]["cores"].size());
97 0 : std::copy(sched_data[d]["cores"].begin(), sched_data[d]["cores"].end(), this->puids_from_file[d].begin());
98 0 : r = sched_data[d]["cores"].size();
99 : }
100 0 : else if (sched_data[d]["cores"].is_number_unsigned())
101 0 : r = sched_data[d]["cores"];
102 : else
103 : {
104 0 : std::stringstream message;
105 0 : message << "Unexpected type for 'cores' field (should be unsigned integer or array of unsigned integers).";
106 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
107 0 : }
108 :
109 0 : if (sched_data[d]["tasks"].is_number_unsigned())
110 0 : this->solution_from_file.push_back(std::make_pair(sched_data[d]["tasks"], r));
111 : else
112 : {
113 0 : std::stringstream message;
114 0 : message << "Unexpected type for 'tasks' field (should be unsigned integer).";
115 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
116 0 : }
117 :
118 0 : if (sched_data[d].contains("sync_buff_size"))
119 : {
120 0 : if (d == sched_data.size() - 1)
121 : {
122 0 : std::stringstream message;
123 0 : message << "The 'sync_buff_size' field cannot be set on the last stage.";
124 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
125 0 : }
126 0 : if (!sched_data[d]["sync_buff_size"].is_number_unsigned())
127 : {
128 0 : std::stringstream message;
129 0 : message << "Unexpected type for 'sync_buff_size' field (should be unsigned integer).";
130 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
131 0 : }
132 :
133 0 : size_t cur_buff_size(sched_data[d]["sync_buff_size"]);
134 0 : this->sync_buff_sizes_from_file[d] = cur_buff_size;
135 : }
136 :
137 0 : if (sched_data[d].contains("sync_waiting_type"))
138 : {
139 0 : if (d == sched_data.size() - 1)
140 : {
141 0 : std::stringstream message;
142 0 : message << "The 'sync_waiting_type' field cannot be set on the last stage.";
143 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
144 0 : }
145 0 : if (!sched_data[d]["sync_waiting_type"].is_string())
146 : {
147 0 : std::stringstream message;
148 0 : message << "Unexpected type for 'sync_waiting_type' field (should be a string).";
149 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
150 0 : }
151 :
152 0 : std::string cur_sync_waiting_type(sched_data[d]["sync_waiting_type"]);
153 0 : if (cur_sync_waiting_type != "active" && cur_sync_waiting_type != "passive")
154 : {
155 0 : std::stringstream message;
156 : message << "Unexpected value for 'sync_waiting_type' field (should be a 'active' or 'passive', given = "
157 0 : << cur_sync_waiting_type << ").";
158 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
159 0 : }
160 :
161 0 : if (cur_sync_waiting_type == "active") this->sync_active_waitings_from_file[d] = true;
162 0 : }
163 :
164 0 : size_t inc(sched_data[d]["tasks"]);
165 0 : n_tasks_json += inc;
166 : }
167 :
168 0 : if (n_tasks_json != sequence.get_tasks_per_threads()[0].size())
169 : {
170 0 : std::stringstream message;
171 : message << "The number of tasks in the json file differs from the number of tasks in the sequence "
172 0 : << "('n_tasks_json' = " << n_tasks_json
173 0 : << ", 'sequence.get_tasks_per_threads()[0].size()' = " << sequence.get_tasks_per_threads()[0].size()
174 0 : << ".";
175 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
176 0 : }
177 0 : }
178 :
179 : /*######################################### JSON SECOND VERSION ########################################################
180 : #######################################################################################################################*/
181 : #ifdef SPU_HWLOC
182 : hwloc_topology_t topology;
183 : std::vector<std::size_t>
184 0 : get_pu_from_core(int id)
185 : {
186 0 : std::vector<std::size_t> core_pus;
187 0 : hwloc_obj_t core_obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_CORE, id);
188 :
189 0 : if (core_obj == nullptr)
190 : {
191 0 : std::stringstream message;
192 0 : message << "No core with id " << id << " found in the topology.";
193 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
194 0 : }
195 0 : for (hwloc_obj_t child = core_obj->first_child; child != nullptr; child = child->next_sibling)
196 : {
197 0 : if (child->type == HWLOC_OBJ_PU)
198 : {
199 0 : core_pus.push_back(child->logical_index);
200 : }
201 : }
202 0 : return core_pus;
203 0 : }
204 : #endif
205 : std::regex pu_single_regex(R"(^PU(\d+)$)");
206 : std::regex pu_range_regex(R"(^PU(\d+)-(\d+)$)");
207 : std::regex core_single_regex(R"(^core(\d+)$)");
208 : std::regex core_range_regex(R"(^core(\d+)-(\d+)$)");
209 :
210 : std::vector<std::vector<size_t>>
211 0 : get_node_pus_from_node(const std::string& node_str)
212 : {
213 0 : std::smatch match;
214 0 : std::vector<std::vector<size_t>> pu_vector;
215 :
216 0 : if (std::regex_match(node_str, match, pu_single_regex))
217 : {
218 0 : size_t pu_id = std::stoi(match[1].str());
219 0 : pu_vector.push_back({ pu_id });
220 : }
221 0 : else if (std::regex_match(node_str, match, pu_range_regex))
222 : {
223 0 : size_t pu_start = std::stoi(match[1].str());
224 0 : size_t pu_end = std::stoi(match[2].str());
225 0 : for (size_t pu_id = pu_start; pu_id <= pu_end; ++pu_id)
226 : {
227 0 : pu_vector.push_back({ pu_id });
228 : }
229 : }
230 0 : else if (std::regex_match(node_str, match, core_single_regex))
231 : {
232 : #ifdef SPU_HWLOC
233 0 : size_t core_id = std::stoi(match[1].str());
234 0 : pu_vector.push_back(get_pu_from_core(core_id));
235 : #else
236 : std::stringstream message;
237 : message << "Using the V2 json format pinning to cores feature"
238 : << "requires linking with the 'hwloc' library.";
239 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
240 : #endif
241 : }
242 0 : else if (std::regex_match(node_str, match, core_range_regex))
243 : {
244 : #ifdef SPU_HWLOC
245 0 : size_t core_start = std::stoi(match[1].str());
246 0 : size_t core_end = std::stoi(match[2].str());
247 0 : for (size_t core_id = core_start; core_id <= core_end; ++core_id)
248 0 : pu_vector.push_back(get_pu_from_core(core_id));
249 : #else
250 : std::stringstream message;
251 : message << "Using the V2 json format pinning to cores feature"
252 : << "requires linking with the 'hwloc' library.";
253 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
254 : #endif
255 : }
256 : else
257 : {
258 0 : std::stringstream message;
259 0 : message << "Invalid node string format: " << node_str;
260 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
261 0 : }
262 0 : return pu_vector;
263 0 : }
264 :
265 : void
266 0 : Scheduler_from_file::build_stage_policy_packed(std::vector<std::vector<size_t>>& pu_list, size_t n_replicates)
267 : {
268 0 : size_t pu_index = 0;
269 0 : size_t pu_list_size = pu_list.size();
270 0 : this->puids_from_file.push_back({});
271 0 : for (size_t i = 0; i < n_replicates; i++)
272 : {
273 : // Check if the current PU list is empty
274 0 : if (pu_list.empty())
275 : {
276 0 : std::stringstream message;
277 0 : message << "Consumed the list of all avalable PUs during construction.";
278 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
279 0 : }
280 0 : this->puids_from_file.back().push_back(pu_list[pu_index][0]);
281 :
282 0 : pu_list[pu_index].erase(pu_list[pu_index].begin()); // Remove the first PU from the list
283 0 : if (pu_list[pu_index].empty())
284 : {
285 0 : pu_list.erase(pu_list.begin() + pu_index); // Remove the empty list
286 0 : pu_index--;
287 0 : pu_list_size--;
288 : }
289 0 : if (pu_list_size > 0) pu_index = (pu_index + 1) % pu_list_size; // Move to the next PU in the list
290 : }
291 0 : }
292 :
293 : void
294 0 : Scheduler_from_file::build_stage_policy_guided(std::vector<std::vector<size_t>>& pu_list, size_t n_replicates)
295 : {
296 0 : size_t pu_list_size = pu_list.size();
297 0 : this->puids_from_file.push_back({});
298 0 : for (size_t j = 0; j < pu_list_size; j++)
299 0 : this->puids_from_file.back().push_back(pu_list[j][0]);
300 0 : }
301 :
302 : void
303 0 : Scheduler_from_file::build_stage_policy_distant(std::vector<std::vector<size_t>>& pu_list,
304 : size_t n_replicates,
305 : size_t curr_type_index,
306 : size_t smt_value)
307 : {
308 0 : size_t pu_index = 0;
309 0 : size_t pu_list_size = pu_list.size();
310 0 : this->puids_from_file.push_back({});
311 0 : for (size_t i = 0; i < n_replicates; i++)
312 : {
313 : // Check if the current PU list is empty
314 0 : if (pu_list.empty())
315 : {
316 0 : std::stringstream message;
317 0 : message << "Consumed the list of all avalable PUs during construction.";
318 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
319 0 : }
320 : // Compute the index of the PU to use
321 0 : pu_index = ((curr_type_index + i) % 2) * (pu_list_size / (2 * smt_value));
322 0 : this->puids_from_file.back().push_back(pu_list[pu_index][0]);
323 :
324 0 : pu_list[pu_index].erase(pu_list[pu_index].begin()); // Remove the first PU from the list
325 0 : if (pu_list[pu_index].empty())
326 : {
327 0 : pu_list.erase(pu_list.begin() + pu_index); // Remove the empty list
328 0 : pu_index--;
329 0 : pu_list_size--;
330 : }
331 : }
332 0 : }
333 :
334 : void
335 0 : Scheduler_from_file::contsruct_policy_v2(json& data, runtime::Sequence& sequence)
336 : {
337 0 : if (!data.contains("resources"))
338 : {
339 0 : std::stringstream message;
340 0 : message << "No ressources information in the json file.";
341 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
342 0 : }
343 0 : auto& resources = data["resources"];
344 :
345 0 : if (!resources.contains("p-core"))
346 : {
347 0 : std::stringstream message;
348 0 : message << "p-cores informations are not specified in the json file.";
349 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
350 0 : }
351 :
352 0 : if (!resources.contains("e-core"))
353 : {
354 0 : std::stringstream message;
355 0 : message << "e-cores informations are not specified in the json file.";
356 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
357 0 : }
358 :
359 0 : auto& p_core_ressources = resources["p-core"];
360 0 : auto& e_core_ressources = resources["e-core"];
361 :
362 0 : if (!p_core_ressources.contains("node-list"))
363 : {
364 0 : std::stringstream message;
365 0 : message << "p-cores list is not given in the json file.";
366 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
367 0 : }
368 0 : if (!e_core_ressources.contains("node-list"))
369 : {
370 0 : std::stringstream message;
371 0 : message << "e-cores list is not given in the json file.";
372 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
373 0 : }
374 0 : auto& p_core_list = p_core_ressources["node-list"];
375 0 : auto& e_core_list = e_core_ressources["node-list"];
376 :
377 : // Getting the smt value
378 0 : if (!p_core_ressources.contains("smt"))
379 : {
380 0 : std::stringstream message;
381 0 : message << "p-cores smt value is not given in the json file.";
382 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
383 0 : }
384 0 : size_t p_core_smt = p_core_ressources["smt"];
385 :
386 0 : if (!e_core_ressources.contains("smt"))
387 : {
388 0 : std::stringstream message;
389 0 : message << "e-cores smt value is not given in the json file.";
390 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
391 0 : }
392 0 : size_t e_core_smt = e_core_ressources["smt"];
393 :
394 : // Getting the list of PU of the given lists
395 : #ifdef SPU_HWLOC
396 0 : hwloc_topology_init(&topology);
397 0 : hwloc_topology_load(topology);
398 : #endif
399 : // Creating the p_core_pu_list
400 0 : for (auto& node : p_core_list)
401 : {
402 0 : std::vector<std::vector<size_t>> pu_vector;
403 0 : if (node.is_string())
404 : {
405 0 : pu_vector = get_node_pus_from_node(node);
406 : }
407 0 : else if (node.is_number_integer())
408 : {
409 0 : pu_vector = get_node_pus_from_node("PU" + std::to_string((int)node));
410 : }
411 : else
412 : {
413 0 : std::stringstream message;
414 0 : message << "Invalid type for p-core node: " << node.dump();
415 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
416 0 : }
417 0 : this->p_core_pu_list.insert(this->p_core_pu_list.end(), pu_vector.begin(), pu_vector.end());
418 0 : }
419 0 : if (p_core_smt > 1)
420 : {
421 0 : for (size_t i = 0; i < p_core_smt - 1; i++)
422 : {
423 0 : for (size_t j = 0; j < this->p_core_pu_list.size(); j++)
424 : {
425 0 : if (this->p_core_pu_list[j].size() > 1)
426 : {
427 0 : this->p_core_pu_list.push_back({ this->p_core_pu_list[j][1] });
428 0 : this->p_core_pu_list[j].erase(this->p_core_pu_list[j].begin() + 1);
429 : }
430 : }
431 : }
432 : }
433 : // Creating the e_core_pu_list
434 0 : for (auto& node : e_core_list)
435 : {
436 0 : std::vector<std::vector<size_t>> pu_vector;
437 0 : if (node.is_string())
438 : {
439 0 : pu_vector = get_node_pus_from_node(node);
440 : }
441 0 : else if (node.is_number_integer())
442 : {
443 0 : pu_vector = get_node_pus_from_node("PU" + std::to_string((int)node));
444 : }
445 : else
446 : {
447 0 : std::stringstream message;
448 0 : message << "Invalid type for p-core node: " << node.dump();
449 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
450 0 : }
451 0 : this->e_core_pu_list.insert(this->e_core_pu_list.end(), pu_vector.begin(), pu_vector.end());
452 0 : }
453 0 : if (e_core_smt > 1)
454 : {
455 0 : for (size_t i = 0; i < e_core_smt - 1; i++)
456 : {
457 0 : for (size_t j = 0; j < this->e_core_pu_list.size(); j++)
458 : {
459 0 : if (this->e_core_pu_list[j].size() > 1)
460 : {
461 0 : this->e_core_pu_list.push_back({ this->e_core_pu_list[j][1] });
462 0 : this->e_core_pu_list[j].erase(this->e_core_pu_list[j].begin() + 1);
463 : }
464 : }
465 : }
466 : }
467 :
468 : // Generating the solution_from_file
469 0 : if (!data.contains("schedule"))
470 : {
471 0 : std::stringstream message;
472 0 : message << "The current json file does not contain the required 'schedule' field.";
473 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
474 0 : }
475 :
476 0 : auto sched_data = data["schedule"];
477 0 : if (!sched_data.is_array())
478 : {
479 0 : std::stringstream message;
480 0 : message << "Unexpected type for the 'schedule' field (should be an array).";
481 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
482 0 : }
483 : // Getting information about wait type and buffer size
484 0 : this->sync_buff_sizes_from_file.resize(sched_data.size() - 1, 1);
485 0 : this->sync_active_waitings_from_file.resize(sched_data.size() - 1, false);
486 :
487 : // Starting the core allocation algorithme
488 0 : size_t n_tasks_json = 0;
489 0 : size_t curr_p_core_stage = 0;
490 0 : size_t curr_e_core_stage = 0;
491 0 : for (size_t d = 0; d < sched_data.size(); d++)
492 : {
493 : // Checking task entry
494 0 : if (!sched_data[d].contains("tasks"))
495 : {
496 0 : std::stringstream message;
497 0 : message << "The current entry does not contain the 'tasks' field.";
498 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
499 0 : }
500 0 : if (!sched_data[d]["tasks"].is_number_integer())
501 : {
502 0 : std::stringstream message;
503 0 : message << "Unexpected type for 'tasks' field (should be an integer).";
504 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
505 0 : }
506 0 : n_tasks_json += (size_t)sched_data[d]["tasks"];
507 : // Checking if the threads entry
508 0 : if (!sched_data[d].contains("threads"))
509 : {
510 0 : std::stringstream message;
511 0 : message << "The current entry does not contain the 'threads' field.";
512 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
513 0 : }
514 0 : if (!sched_data[d]["threads"].is_number_integer())
515 : {
516 0 : std::stringstream message;
517 0 : message << "Unexpected type for 'threads' field (should be an integer).";
518 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
519 0 : }
520 0 : size_t n_replicates = sched_data[d]["threads"];
521 :
522 : // Generating solution_from_file
523 0 : this->solution_from_file.push_back(std::make_pair((size_t)sched_data[d]["tasks"], n_replicates));
524 :
525 : // Getting the currect stage pinning strategy
526 0 : if (!sched_data[d].contains("pinning-policy"))
527 : {
528 0 : std::stringstream message;
529 0 : message << "The current entry does not contain the 'pinning-policy' field.";
530 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
531 0 : }
532 0 : if (!sched_data[d]["pinning-policy"].is_string())
533 : {
534 0 : std::stringstream message;
535 0 : message << "Unexpected type for 'pinning-policy' field (should be a string).";
536 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
537 0 : }
538 0 : this->pinning_policy.push_back(sched_data[d]["pinning-policy"]);
539 :
540 : // Checking the type of cores to which the threads will be pinned
541 0 : if (!sched_data[d].contains("core-type"))
542 : {
543 0 : std::stringstream message;
544 0 : message << "The current entry does not contain the 'core-type' field.";
545 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
546 0 : }
547 0 : if (!sched_data[d]["core-type"].is_string())
548 : {
549 0 : std::stringstream message;
550 0 : message << "Unexpected type for 'core-type' field (should be a string).";
551 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
552 0 : }
553 0 : std::string core_type = sched_data[d]["core-type"];
554 0 : if (core_type == "p-core")
555 : {
556 0 : if (this->pinning_policy.back() == "packed")
557 : {
558 0 : build_stage_policy_packed(this->p_core_pu_list, n_replicates);
559 : }
560 0 : else if (this->pinning_policy.back() == "guided")
561 : {
562 0 : build_stage_policy_guided(this->p_core_pu_list, n_replicates);
563 : }
564 0 : else if (this->pinning_policy.back() == "distant")
565 : {
566 :
567 0 : build_stage_policy_distant(this->p_core_pu_list, n_replicates, curr_p_core_stage, p_core_smt);
568 : }
569 0 : else if (this->pinning_policy.back() == "loose")
570 : {
571 0 : this->puids_from_file.push_back({ 1 });
572 : }
573 0 : else if (this->pinning_policy.back() != "loose")
574 : {
575 0 : this->pinning_policy.pop_back();
576 0 : this->pinning_policy.push_back("loose");
577 0 : this->puids_from_file.push_back({ 1 });
578 : }
579 0 : curr_p_core_stage++;
580 : }
581 0 : else if (core_type == "e-core")
582 : {
583 0 : if (this->pinning_policy.back() == "packed")
584 : {
585 0 : build_stage_policy_packed(this->e_core_pu_list, n_replicates);
586 : }
587 0 : else if (this->pinning_policy.back() == "guided")
588 : {
589 0 : build_stage_policy_guided(this->e_core_pu_list, n_replicates);
590 : }
591 0 : else if (this->pinning_policy.back() == "distant")
592 : {
593 0 : build_stage_policy_distant(this->e_core_pu_list, n_replicates, curr_e_core_stage, e_core_smt);
594 : }
595 0 : else if (this->pinning_policy.back() == "loose")
596 : {
597 0 : this->puids_from_file.push_back({ 1 });
598 : }
599 0 : else if (this->pinning_policy.back() != "loose")
600 : {
601 0 : this->pinning_policy.pop_back();
602 0 : this->pinning_policy.push_back("loose");
603 0 : this->puids_from_file.push_back({ 1 });
604 : }
605 0 : curr_e_core_stage++;
606 : }
607 : else
608 : {
609 0 : std::stringstream message;
610 : message << "Unexpected value for 'core-type' field (should be 'p-core' or 'e-core', given = " << core_type
611 0 : << ").";
612 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
613 0 : }
614 : // Checking if the current stage has inter-stage buffer size
615 0 : if (sched_data[d].contains("sync_buff_size"))
616 : {
617 0 : if (!sched_data[d]["sync_buff_size"].is_number_unsigned())
618 : {
619 0 : std::stringstream message;
620 0 : message << "Unexpected type for 'sync_buff_size' field (should be unsigned integer).";
621 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
622 0 : }
623 : else
624 : {
625 0 : this->sync_buff_sizes_from_file[d] = (size_t)sched_data[d]["sync_buff_size"];
626 : }
627 : }
628 : // Checking if the current stage has a synchronization type
629 0 : if (sched_data[d].contains("sync_waiting_type"))
630 : {
631 0 : if (d == sched_data.size() - 1)
632 : {
633 0 : std::stringstream message;
634 0 : message << "The 'sync_waiting_type' field cannot be set on the last stage.";
635 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
636 0 : }
637 0 : if (!sched_data[d]["sync_waiting_type"].is_string())
638 : {
639 0 : std::stringstream message;
640 0 : message << "Unexpected type for 'sync_waiting_type' field (should be a string).";
641 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
642 0 : }
643 :
644 0 : std::string cur_sync_waiting_type(sched_data[d]["sync_waiting_type"]);
645 0 : if (cur_sync_waiting_type != "active" && cur_sync_waiting_type != "passive")
646 : {
647 0 : std::stringstream message;
648 : message << "Unexpected value for 'sync_waiting_type' field (should be a 'active' or 'passive', given = "
649 0 : << cur_sync_waiting_type << ").";
650 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
651 0 : }
652 0 : if (cur_sync_waiting_type == "active") this->sync_active_waitings_from_file[d] = true;
653 0 : }
654 0 : }
655 : // Checking if the number of tasks in the json file is equal to the number of tasks in the sequence
656 0 : if (n_tasks_json != sequence.get_tasks_per_threads()[0].size())
657 : {
658 0 : std::stringstream message;
659 : message << "The number of tasks in the json file differs from the number of tasks in the sequence "
660 0 : << "('n_tasks_json' = " << n_tasks_json
661 0 : << ", 'sequence.get_tasks_per_threads()[0].size()' = " << sequence.get_tasks_per_threads()[0].size()
662 0 : << ").";
663 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
664 0 : }
665 0 : }
666 : /*######################################################################################################################
667 : #######################################################################################################################*/
668 :
669 : void
670 0 : Scheduler_from_file::schedule()
671 : {
672 0 : this->solution = this->solution_from_file;
673 0 : }
674 :
675 : std::vector<size_t>
676 0 : Scheduler_from_file::get_sync_buff_sizes() const
677 : {
678 0 : return this->sync_buff_sizes_from_file;
679 : }
680 :
681 : std::vector<bool>
682 0 : Scheduler_from_file::get_sync_active_waitings() const
683 : {
684 0 : return this->sync_active_waitings_from_file;
685 : }
686 :
687 : std::vector<bool>
688 0 : Scheduler_from_file::get_thread_pinnings() const
689 : {
690 0 : std::vector<bool> threads_pin(this->solution_from_file.size(), false);
691 0 : for (size_t s = 0; s < this->puids_from_file.size(); s++)
692 0 : if (this->puids_from_file[s].size()) threads_pin[s] = true;
693 0 : return threads_pin;
694 0 : }
695 :
696 : std::string
697 0 : Scheduler_from_file::get_threads_mapping() const
698 : {
699 0 : std::string pinning_policy_str;
700 0 : if (this->puids_from_file.size())
701 : {
702 0 : for (size_t sta = 0; sta < this->pinning_policy.size(); ++sta)
703 : {
704 0 : if (this->file_version == 1 || (this->file_version == 2 && this->pinning_policy[sta] == "packed") ||
705 0 : (this->file_version == 2 && this->pinning_policy[sta] == "distant"))
706 : {
707 0 : if (sta != 0) pinning_policy_str += " | ";
708 0 : for (size_t i = 0; i < this->puids_from_file[sta].size(); i++)
709 : {
710 : pinning_policy_str +=
711 0 : std::string((i == 0) ? "" : "; ") + "PU_" + std::to_string(this->puids_from_file[sta][i]);
712 : }
713 0 : if (!this->puids_from_file[sta].size()) pinning_policy_str += "NO_PIN";
714 : }
715 0 : else if (this->file_version == 2 && this->pinning_policy[sta] == "guided")
716 : {
717 0 : if (sta != 0) pinning_policy_str += " | ";
718 0 : for (size_t replicate = 0; this->solution_from_file[sta].second > replicate; replicate++)
719 : {
720 0 : if (replicate != 0) pinning_policy_str += " ; ";
721 0 : for (size_t i = 0; i < this->puids_from_file[sta].size(); i++)
722 : {
723 : pinning_policy_str +=
724 0 : std::string((i == 0) ? "" : ", ") + "PU_" + std::to_string(this->puids_from_file[sta][i]);
725 : }
726 : }
727 0 : if (!this->puids_from_file[sta].size()) pinning_policy_str += "NO_PIN";
728 : }
729 0 : else if (this->pinning_policy[sta] == "loose")
730 : {
731 0 : if (sta != 0) pinning_policy_str += " | ";
732 0 : pinning_policy_str += "MACHINE_0";
733 : }
734 : else
735 : {
736 0 : std::stringstream message;
737 0 : message << "Unknown pinning strategy: " << this->pinning_policy[sta] << " at stage number:" << sta;
738 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
739 0 : }
740 : }
741 : }
742 : else
743 0 : pinning_policy_str = Scheduler::get_threads_mapping();
744 :
745 0 : return pinning_policy_str;
746 0 : }
|