aboutsummaryrefslogtreecommitdiffstats
path: root/native/src
diff options
context:
space:
mode:
Diffstat (limited to 'native/src')
-rw-r--r--native/src/edf/gel_pl.cpp147
1 files changed, 97 insertions, 50 deletions
diff --git a/native/src/edf/gel_pl.cpp b/native/src/edf/gel_pl.cpp
index 53ae575..f0f9303 100644
--- a/native/src/edf/gel_pl.cpp
+++ b/native/src/edf/gel_pl.cpp
@@ -6,8 +6,10 @@
6#include <limits> 6#include <limits>
7#include <algorithm> 7#include <algorithm>
8#include <cmath> 8#include <cmath>
9#include <iostream>
9 10
10static bool reversed_order(double first, double second) { 11static bool reversed_order(const fractional_t& first,
12 const fractional_t& second) {
11 return second < first; 13 return second < first;
12} 14}
13 15
@@ -16,8 +18,8 @@ GELPl::GELPl(Scheduler sched, unsigned int num_processors, const TaskSet& ts,
16:no_cpus(num_processors), tasks(ts), rounds(num_rounds) 18:no_cpus(num_processors), tasks(ts), rounds(num_rounds)
17{ 19{
18 std::vector<unsigned long> pps; 20 std::vector<unsigned long> pps;
19 double S; 21 fractional_t S = 0;
20 std::vector<double> Y_ints; 22 std::vector<fractional_t> Y_ints;
21 23
22 int task_count = tasks.get_task_count(); 24 int task_count = tasks.get_task_count();
23 // Reserve capacity in all vectors to minimize allocation costs. 25 // Reserve capacity in all vectors to minimize allocation costs.
@@ -29,8 +31,8 @@ GELPl::GELPl(Scheduler sched, unsigned int num_processors, const TaskSet& ts,
29 // For faster lookups 31 // For faster lookups
30 utilizations.reserve(task_count); 32 utilizations.reserve(task_count);
31 for (int i = 0; i < task_count; i++) { 33 for (int i = 0; i < task_count; i++) {
32 utilizations.push_back(double(tasks[i].get_wcet()) 34 utilizations.push_back(tasks[i].get_wcet());
33 / double(tasks[i].get_period())); 35 utilizations[i] /= tasks[i].get_period();
34 } 36 }
35 37
36 unsigned long min_pp = std::numeric_limits<unsigned long>::max(); 38 unsigned long min_pp = std::numeric_limits<unsigned long>::max();
@@ -50,36 +52,60 @@ GELPl::GELPl(Scheduler sched, unsigned int num_processors, const TaskSet& ts,
50 52
51 // Reduce to compute minimum. Also compute Y intercepts, S_i values, and 53 // Reduce to compute minimum. Also compute Y intercepts, S_i values, and
52 // S. 54 // S.
53 S = 0.0;
54 for (int i = 0; i < task_count; i++) { 55 for (int i = 0; i < task_count; i++) {
55 pps[i] -= min_pp; 56 pps[i] -= min_pp;
56 const Task& task = tasks[i]; 57 const Task& task = tasks[i];
57 double wcet = double(task.get_wcet()); 58 unsigned long wcet = task.get_wcet();
58 double period = double(task.get_period()); 59 unsigned long period = task.get_period();
59 S_i[i] = std::max(0.0, wcet * (1.0 - double(pps[i])/ period)); 60 S_i.push_back(pps[i]);
60 S += S_i[i]; 61 fractional_t& S_i_i = S_i[i];
61 Y_ints.push_back((0.0 - wcet/no_cpus) * (wcet / period) 62 S_i_i *= -1;
62 + task.get_wcet() - S_i[i]); 63 S_i_i /= period;
64 S_i_i += 1;
65 S_i_i *= wcet;
66 if (S_i_i < 0) {
67 S_i_i = 0;
68 }
69 S += S_i_i;
70 Y_ints.push_back(wcet);
71 fractional_t& Y_ints_i = Y_ints[i];
72 Y_ints_i *= -1;
73 Y_ints_i /= no_cpus;
74 Y_ints_i *= utilizations[i];
75 Y_ints_i += wcet;
76 Y_ints_i -= S_i_i;
63 } 77 }
64 78
65 double s; 79 fractional_t s;
66 if (rounds == 0) { 80 if (rounds == 0) {
67 s = compute_exact_s(S, Y_ints); 81 compute_exact_s(S, Y_ints, s);
68 } 82 }
69 else { 83 else {
70 s = compute_binsearch_s(S, Y_ints); 84 compute_binsearch_s(S, Y_ints, s);
71 } 85 }
72 86
73 for (int i = 0; i < task_count; i++) { 87 for (int i = 0; i < task_count; i++) {
88 fractional_t x_i = s;
89 fractional_t x_comp = tasks[i].get_wcet();
90 x_comp /= no_cpus;
91 x_i -= x_comp;
92 // Compute ceiling
93 integral_t xi_ceil = x_i.get_num();
94 mpz_cdiv_q(xi_ceil.get_mpz_t(),
95 x_i.get_num().get_mpz_t(),
96 x_i.get_den().get_mpz_t());
74 bounds.push_back(pps[i] 97 bounds.push_back(pps[i]
75 + tasks[i].get_wcet() 98 + tasks[i].get_wcet()
76 + (unsigned long)std::ceil( 99 + xi_ceil.get_ui());
77 s - (double(tasks[i].get_wcet() / double(no_cpus))))); 100 G_i.push_back(s);
78 G_i.push_back(Y_ints[i] + s * utilizations[i]); 101 G_i[i] *= utilizations[i];
102 G_i[i] += Y_ints[i];
79 } 103 }
80} 104}
81 105
82double GELPl::compute_exact_s(double S, const std::vector<double>& Y_ints) { 106void GELPl::compute_exact_s(const fractional_t& S,
107 const std::vector<fractional_t>& Y_ints,
108 fractional_t& s) {
83 int task_count = tasks.get_task_count(); 109 int task_count = tasks.get_task_count();
84 110
85 std::vector<ReplacementType> replacements; 111 std::vector<ReplacementType> replacements;
@@ -88,19 +114,22 @@ double GELPl::compute_exact_s(double S, const std::vector<double>& Y_ints) {
88 // We can ignore parallel and identical lines - either don't 114 // We can ignore parallel and identical lines - either don't
89 // intersect or we don't care which is picked. 115 // intersect or we don't care which is picked.
90 if (utilizations[i] != utilizations[j]) { 116 if (utilizations[i] != utilizations[j]) {
91 double intersect = (Y_ints[j] - Y_ints[i]) 117 fractional_t intersect_den = utilizations[i];
92 / (utilizations[i] - utilizations[j]); 118 intersect_den -= utilizations[j];
119 fractional_t intersect = Y_ints[j];
120 intersect -= Y_ints[i];
121 intersect /= intersect_den;
93 ReplacementType replacement; 122 ReplacementType replacement;
94 replacement.location = intersect; 123 replacement.location = intersect;
95 if (intersect >= 0.0) { 124 if (intersect >= 0) {
96 if (utilizations[i] < utilizations[j]) { 125 if (utilizations[i] < utilizations[j]) {
97 replacement.old_task = i; 126 replacement.old_task = i;
98 replacement.old_task_utilization = utilizations[i]; 127 replacement.old_task_utilization = utilizations[i];
99 replacement.new_task = j; 128 replacement.new_task = j;
100 } 129 }
101 else { 130 else {
102 replacement.old_task = j; 131 replacement.old_task = j;
103 replacement.old_task_utilization = utilizations[j]; 132 replacement.old_task_utilization = utilizations[j];
104 replacement.new_task = i; 133 replacement.new_task = i;
105 } 134 }
106 replacements.push_back(replacement); 135 replacements.push_back(replacement);
@@ -113,15 +142,16 @@ double GELPl::compute_exact_s(double S, const std::vector<double>& Y_ints) {
113 std::vector<bool> task_pres; 142 std::vector<bool> task_pres;
114 task_pres.assign(task_count, false); 143 task_pres.assign(task_count, false);
115 144
116 double current_value = S; 145 fractional_t current_value = S;
117 double current_slope = -1 * no_cpus; 146 fractional_t current_slope = no_cpus;
147 current_slope *= -1;
118 148
119 std::vector<TaggedValue> init_pairs; 149 std::vector<TaggedValue> init_pairs;
120 init_pairs.reserve(task_count); 150 init_pairs.reserve(task_count);
121 for (int i = 0; i < task_count; i++) { 151 for (int i = 0; i < task_count; i++) {
122 TaggedValue new_pair; 152 TaggedValue new_pair;
123 new_pair.task = i; 153 new_pair.task = i;
124 new_pair.value = Y_ints[i]; 154 new_pair.value = Y_ints[i];
125 init_pairs.push_back(new_pair); 155 init_pairs.push_back(new_pair);
126 } 156 }
127 157
@@ -138,15 +168,21 @@ double GELPl::compute_exact_s(double S, const std::vector<double>& Y_ints) {
138 } 168 }
139 169
140 unsigned int rindex = 0; 170 unsigned int rindex = 0;
141 double next_s = 0.0; 171 fractional_t next_s = 0;
142 double zero = std::numeric_limits<double>::infinity(); 172 s = 1;
143 while (zero > next_s) { 173 while (s > next_s) {
144 double current_s = next_s; 174 fractional_t current_s = next_s;
145 zero = current_s - current_value / current_slope; 175 s = current_value;
176 s /= current_slope;
177 s *= -1;
178 s += current_s;
146 if (rindex < replacements.size()) { 179 if (rindex < replacements.size()) {
147 ReplacementType replacement = replacements[rindex]; 180 ReplacementType replacement = replacements[rindex];
148 next_s = replacement.location; 181 next_s = replacement.location;
149 current_value += (next_s - current_s) * current_slope; 182 fractional_t val_inc = next_s;
183 val_inc -= current_s;
184 val_inc *= current_slope;
185 current_value += val_inc;
150 // Apply replacement, if appropriate 186 // Apply replacement, if appropriate
151 if (task_pres[replacement.old_task] 187 if (task_pres[replacement.old_task]
152 && !task_pres[replacement.new_task]) { 188 && !task_pres[replacement.new_task]) {
@@ -158,23 +194,28 @@ double GELPl::compute_exact_s(double S, const std::vector<double>& Y_ints) {
158 rindex++; 194 rindex++;
159 } 195 }
160 else { 196 else {
161 next_s = std::numeric_limits<double>::infinity(); 197 next_s = s;
198 next_s += 1;
162 } 199 }
163 } 200 }
164 return zero; 201 // At this point, "s" should be the appropriate return value
165} 202}
166 203
167double GELPl::compute_binsearch_s(double S, const std::vector<double>& Y_ints) { 204void GELPl::compute_binsearch_s(const fractional_t& S,
168 double min_s = 0.0; 205 const std::vector<fractional_t>& Y_ints,
169 double max_s = 1.0; 206 fractional_t& s) {
170 while (compute_M(max_s, S, Y_ints) > 0) { 207 fractional_t min_s = 0;
208 fractional_t max_s = 1;
209 while (!M_lt_0(max_s, S, Y_ints)) {
171 min_s = max_s; 210 min_s = max_s;
172 max_s *= 2.0; 211 max_s *= 2;
173 } 212 }
174 213
175 for (int i = 0; i < rounds; i++) { 214 for (int i = 0; i < rounds; i++) {
176 double middle = (min_s + max_s) / 2.0; 215 fractional_t middle = min_s;
177 if (compute_M(middle, S, Y_ints) < 0) { 216 middle += max_s;
217 middle /= 2;
218 if (M_lt_0(middle, S, Y_ints)) {
178 max_s = middle; 219 max_s = middle;
179 } 220 }
180 else { 221 else {
@@ -183,24 +224,30 @@ double GELPl::compute_binsearch_s(double S, const std::vector<double>& Y_ints) {
183 } 224 }
184 225
185 // max_s is guaranteed to be a legal bound. 226 // max_s is guaranteed to be a legal bound.
186 return max_s; 227 s = max_s;
187} 228}
188 229
189double GELPl::compute_M(double s, double S, const std::vector<double>& Y_ints) { 230bool GELPl::M_lt_0(const fractional_t& s, const fractional_t& S,
190 std::vector<double> Gvals; 231 const std::vector<fractional_t>& Y_ints) {
232 std::vector<fractional_t> Gvals;
191 int task_count = tasks.get_task_count(); 233 int task_count = tasks.get_task_count();
192 for (int i = 0; i < task_count; i++) { 234 for (int i = 0; i < task_count; i++) {
193 Gvals.push_back(Y_ints[i] + utilizations[i] * s); 235 Gvals.push_back(utilizations[i]);
236 Gvals[i] *= s;
237 Gvals[i] += Y_ints[i];
194 } 238 }
195 239
196 // Again, more efficient computation by not totally sorting. 240 // Again, more efficient computation by not totally sorting.
197 std::nth_element(Gvals.begin(), Gvals.begin() + no_cpus - 2, Gvals.end(), 241 std::nth_element(Gvals.begin(), Gvals.begin() + no_cpus - 2, Gvals.end(),
198 reversed_order); 242 reversed_order);
199 double to_return = S - no_cpus * s; 243 fractional_t final_val = no_cpus;
244 final_val *= -1;
245 final_val *= s;
246 final_val += S;
200 247
201 for (int i = 0; i < no_cpus - 1; i++) { 248 for (int i = 0; i < no_cpus - 1; i++) {
202 to_return += Gvals[i]; 249 final_val += Gvals[i];
203 } 250 }
204 251
205 return to_return; 252 return (final_val < 0);
206} 253}