LCOV - code coverage report
Current view: top level - src/Scheduler/From_file - Scheduler_from_file.cpp (source / functions) Hit Total Coverage
Test: streampu_clean.info Lines: 0 436 0.0 %
Date: 2025-10-30 03:49:03 Functions: 0 14 0.0 %

          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 : }

Generated by: LCOV version 1.14