diff options
| author | Jeremy Erickson <jerickso@cs.unc.edu> | 2012-10-29 12:18:48 -0400 |
|---|---|---|
| committer | Jeremy Erickson <jerickso@cs.unc.edu> | 2012-10-29 14:10:32 -0400 |
| commit | 107da1b6a3840b0e39b436ea51686aa381d27b90 (patch) | |
| tree | 92391d2791c6c858ac426c532111fa507cf7f17c | |
| parent | 37dbd04e4f9d8956cf4be1c196e282760aa37011 (diff) | |
Added arbitrary-precision arithmetic to native module
| -rw-r--r-- | native/include/edf/gel_pl.h | 30 | ||||
| -rw-r--r-- | native/src/edf/gel_pl.cpp | 147 | ||||
| -rw-r--r-- | schedcat/sched/edf/gel_pl.py | 69 |
3 files changed, 152 insertions, 94 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 | ||
| 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]; |
