diff options
Diffstat (limited to 'native/src')
| -rw-r--r-- | native/src/edf/gel_pl.cpp | 147 |
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 | ||
| 10 | static bool reversed_order(double first, double second) { | 11 | static 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 | ||
| 82 | double GELPl::compute_exact_s(double S, const std::vector<double>& Y_ints) { | 106 | void 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 | ||
| 167 | double GELPl::compute_binsearch_s(double S, const std::vector<double>& Y_ints) { | 204 | void 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 | ||
| 189 | double GELPl::compute_M(double s, double S, const std::vector<double>& Y_ints) { | 230 | bool 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 | } |
