aboutsummaryrefslogtreecommitdiffstats
path: root/native
diff options
context:
space:
mode:
authorJeremy Erickson <jerickso@cs.unc.edu>2012-10-29 12:18:48 -0400
committerJeremy Erickson <jerickso@cs.unc.edu>2012-10-29 14:10:32 -0400
commit107da1b6a3840b0e39b436ea51686aa381d27b90 (patch)
tree92391d2791c6c858ac426c532111fa507cf7f17c /native
parent37dbd04e4f9d8956cf4be1c196e282760aa37011 (diff)
Added arbitrary-precision arithmetic to native module
Diffstat (limited to 'native')
-rw-r--r--native/include/edf/gel_pl.h30
-rw-r--r--native/src/edf/gel_pl.cpp147
2 files changed, 115 insertions, 62 deletions
diff --git a/native/include/edf/gel_pl.h b/native/include/edf/gel_pl.h
index 4093d95..1127d50 100644
--- a/native/include/edf/gel_pl.h
+++ b/native/include/edf/gel_pl.h
@@ -13,17 +13,21 @@ class GELPl
13 int no_cpus; 13 int no_cpus;
14 const TaskSet& tasks; 14 const TaskSet& tasks;
15 int rounds; 15 int rounds;
16 std::vector<double> S_i; 16 std::vector<fractional_t> S_i;
17 std::vector<double> G_i; 17 std::vector<fractional_t> G_i;
18 18
19 // For faster lookups, to avoid too many conversions. 19 // For faster lookups, to avoid too many conversions.
20 std::vector<double> utilizations; 20 std::vector<fractional_t> utilizations;
21 21
22 double compute_exact_s(double S, const std::vector<double>& Y_ints); 22 void compute_exact_s(const fractional_t& S,
23 double compute_binsearch_s(double S, const std::vector<double>& Y_ints); 23 const std::vector<fractional_t>& Y_ints,
24 fractional_t& s);
25 void compute_binsearch_s(const fractional_t& S,
26 const std::vector<fractional_t>& Y_ints,
27 fractional_t& s);
24 28
25 inline double compute_M(double s, double S, 29 inline bool M_lt_0(const fractional_t& s, const fractional_t& S,
26 const std::vector<double>& Y_ints); 30 const std::vector<fractional_t>& Y_ints);
27 31
28 // These are basically just structs that override operator< to allow 32 // These are basically just structs that override operator< to allow
29 // sort algorithms to work. 33 // sort algorithms to work.
@@ -31,8 +35,8 @@ class GELPl
31 public: 35 public:
32 unsigned int old_task; 36 unsigned int old_task;
33 unsigned int new_task; 37 unsigned int new_task;
34 double location; 38 fractional_t location;
35 double old_task_utilization; 39 fractional_t old_task_utilization;
36 40
37 bool operator<(const ReplacementType& other) const { 41 bool operator<(const ReplacementType& other) const {
38 return (location < other.location) 42 return (location < other.location)
@@ -44,7 +48,7 @@ class GELPl
44 class TaggedValue { 48 class TaggedValue {
45 public: 49 public:
46 unsigned int task; 50 unsigned int task;
47 double value; 51 fractional_t value;
48 52
49 //Order is reversed - we are going to want the largest, rather than the 53 //Order is reversed - we are going to want the largest, rather than the
50 //smallest, values. 54 //smallest, values.
@@ -68,12 +72,14 @@ class GELPl
68 return bounds[index]; 72 return bounds[index];
69 } 73 }
70 74
75 // Converted to double for the sake of Python
71 double get_Si(unsigned int index) { 76 double get_Si(unsigned int index) {
72 return S_i[index]; 77 return S_i[index].get_d();
73 } 78 }
74 79
80 // Converted to double for the sake of Python
75 double get_Gi(unsigned int index) { 81 double get_Gi(unsigned int index) {
76 return G_i[index]; 82 return G_i[index].get_d();
77 } 83 }
78}; 84};
79 85
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}