Line data Source code
1 : #include <cmath>
2 : #include <fstream>
3 : #include <iostream>
4 : #include <limits>
5 : #include <nlohmann/json.hpp>
6 : #include <sstream>
7 : using json = nlohmann::json;
8 :
9 : #include "Scheduler/From_file/Scheduler_from_file.hpp"
10 : #include "Tools/Exception/exception.hpp"
11 :
12 : using namespace spu;
13 : using namespace spu::sched;
14 :
15 0 : Scheduler_from_file::Scheduler_from_file(runtime::Sequence& sequence, const std::string filename)
16 0 : : Scheduler(sequence)
17 : {
18 0 : std::ifstream f(filename);
19 0 : if (!f.good())
20 : {
21 0 : std::stringstream message;
22 0 : message << "The current file cannot be opened ('filename' = " << filename << ").";
23 0 : throw tools::invalid_argument(__FILE__, __LINE__, __func__, message.str());
24 0 : }
25 :
26 0 : json data = json::parse(f);
27 :
28 0 : if (!data.contains("scheduling"))
29 : {
30 0 : std::stringstream message;
31 0 : message << "The current json file does not contain the required 'scheduling' field.";
32 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
33 0 : }
34 :
35 0 : auto sched_data = data["scheduling"];
36 :
37 0 : if (!sched_data.is_array())
38 : {
39 0 : std::stringstream message;
40 0 : message << "Unexpected type for the 'scheduling' field (should be an array).";
41 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
42 0 : }
43 :
44 0 : this->sync_buff_sizes_from_file.resize(sched_data.size() - 1, 1);
45 0 : this->sync_active_waitings_from_file.resize(sched_data.size() - 1, false);
46 :
47 0 : size_t n_tasks_json = 0;
48 0 : for (size_t d = 0; d < sched_data.size(); d++)
49 : {
50 0 : if (!sched_data[d].contains("cores"))
51 : {
52 0 : std::stringstream message;
53 0 : message << "The current entry does not contain the 'cores' field.";
54 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
55 0 : }
56 0 : if (!sched_data[d].contains("tasks"))
57 : {
58 0 : std::stringstream message;
59 0 : message << "The current entry does not contain the 'tasks' field.";
60 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
61 0 : }
62 :
63 : size_t r;
64 0 : if (sched_data[d]["cores"].is_array())
65 : {
66 0 : if (!this->puids_from_file.size()) this->puids_from_file.resize(sched_data.size());
67 :
68 0 : this->puids_from_file[d].resize(sched_data[d]["cores"].size());
69 0 : std::copy(sched_data[d]["cores"].begin(), sched_data[d]["cores"].end(), this->puids_from_file[d].begin());
70 0 : r = sched_data[d]["cores"].size();
71 : }
72 0 : else if (sched_data[d]["cores"].is_number_unsigned())
73 0 : r = sched_data[d]["cores"];
74 : else
75 : {
76 0 : std::stringstream message;
77 0 : message << "Unexpected type for 'cores' field (should be unsigned integer or array of unsigned integers).";
78 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
79 0 : }
80 :
81 0 : if (sched_data[d]["tasks"].is_number_unsigned())
82 0 : this->solution_from_file.push_back(std::make_pair(sched_data[d]["tasks"], r));
83 : else
84 : {
85 0 : std::stringstream message;
86 0 : message << "Unexpected type for 'tasks' field (should be unsigned integer).";
87 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
88 0 : }
89 :
90 0 : if (sched_data[d].contains("sync_buff_size"))
91 : {
92 0 : if (d == sched_data.size() - 1)
93 : {
94 0 : std::stringstream message;
95 0 : message << "The 'sync_buff_size' field cannot be set on the last stage.";
96 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
97 0 : }
98 0 : if (!sched_data[d]["sync_buff_size"].is_number_unsigned())
99 : {
100 0 : std::stringstream message;
101 0 : message << "Unexpected type for 'sync_buff_size' field (should be unsigned integer).";
102 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
103 0 : }
104 :
105 0 : size_t cur_buff_size(sched_data[d]["sync_buff_size"]);
106 0 : this->sync_buff_sizes_from_file[d] = cur_buff_size;
107 : }
108 :
109 0 : if (sched_data[d].contains("sync_waiting_type"))
110 : {
111 0 : if (d == sched_data.size() - 1)
112 : {
113 0 : std::stringstream message;
114 0 : message << "The 'sync_waiting_type' field cannot be set on the last stage.";
115 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
116 0 : }
117 0 : if (!sched_data[d]["sync_waiting_type"].is_string())
118 : {
119 0 : std::stringstream message;
120 0 : message << "Unexpected type for 'sync_waiting_type' field (should be a string).";
121 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
122 0 : }
123 :
124 0 : std::string cur_sync_waiting_type(sched_data[d]["sync_waiting_type"]);
125 0 : if (cur_sync_waiting_type != "active" && cur_sync_waiting_type != "passive")
126 : {
127 0 : std::stringstream message;
128 : message << "Unexpected value for 'sync_waiting_type' field (should be a 'active' or 'passive', given = "
129 0 : << cur_sync_waiting_type << ").";
130 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
131 0 : }
132 :
133 0 : if (cur_sync_waiting_type == "active") this->sync_active_waitings_from_file[d] = true;
134 0 : }
135 :
136 0 : size_t inc(sched_data[d]["tasks"]);
137 0 : n_tasks_json += inc;
138 : }
139 :
140 0 : if (n_tasks_json != sequence.get_tasks_per_threads()[0].size())
141 : {
142 0 : std::stringstream message;
143 : message << "The number of tasks in the json file differs from the number of tasks in the sequence "
144 0 : << "('n_tasks_json' = " << n_tasks_json
145 0 : << ", 'sequence.get_tasks_per_threads()[0].size()' = " << sequence.get_tasks_per_threads()[0].size()
146 0 : << ".";
147 0 : throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
148 0 : }
149 0 : }
150 :
151 0 : Scheduler_from_file::Scheduler_from_file(runtime::Sequence* sequence, const std::string filename)
152 0 : : Scheduler_from_file(*sequence, filename)
153 : {
154 0 : }
155 :
156 : void
157 0 : Scheduler_from_file::schedule()
158 : {
159 0 : this->solution = this->solution_from_file;
160 0 : }
161 :
162 : std::vector<size_t>
163 0 : Scheduler_from_file::get_sync_buff_sizes() const
164 : {
165 0 : return this->sync_buff_sizes_from_file;
166 : }
167 :
168 : std::vector<bool>
169 0 : Scheduler_from_file::get_sync_active_waitings() const
170 : {
171 0 : return this->sync_active_waitings_from_file;
172 : }
173 :
174 : std::vector<bool>
175 0 : Scheduler_from_file::get_thread_pinnings() const
176 : {
177 0 : std::vector<bool> threads_pin(this->solution_from_file.size(), false);
178 0 : for (size_t s = 0; s < this->puids_from_file.size(); s++)
179 0 : if (this->puids_from_file[s].size()) threads_pin[s] = true;
180 0 : return threads_pin;
181 0 : }
182 :
183 : std::string
184 0 : Scheduler_from_file::get_threads_mapping() const
185 : {
186 0 : std::string pinning_policy;
187 0 : if (this->puids_from_file.size())
188 : {
189 0 : for (size_t s = 0; s < this->puids_from_file.size(); s++)
190 : {
191 0 : if (s != 0) pinning_policy += " | ";
192 0 : for (size_t i = 0; i < this->puids_from_file[s].size(); i++)
193 : pinning_policy +=
194 0 : std::string((i == 0) ? "" : "; ") + "PU_" + std::to_string(this->puids_from_file[s][i]);
195 0 : if (!this->puids_from_file[s].size()) pinning_policy += "NO_PIN";
196 : }
197 : }
198 : else
199 0 : pinning_policy = Scheduler::get_threads_mapping();
200 :
201 0 : return pinning_policy;
202 0 : }
|