crown  1.0.0
src/CrownCompositeConsolidation.cpp
Go to the documentation of this file.
00001 // The following definitions might be exchanged for others,
00002 // when integrating the following code into the framework.
00003 // The code implements a greedy heuristic to loadbalance the tasks
00004 // over cores such that the l2-norm of the load vector is minimized.
00005 // This should also minimize the l3-norm of the load vector.
00006 // J. Keller, July 14, 2014
00007 
00008 #include <stdio.h>
00009 #include <stdlib.h>
00010 #include <string.h>
00011 #include <math.h>
00012 #include <iostream>
00013 #include <sstream>
00014 
00015 #include <crown/allocation.h>
00016 #include <crown/mapping.h>
00017 #include <crown/scaling.h>
00018 #include <crown/crown.h>
00019 #include <crown/annealing.h>
00020 #include <crown/CrownCompositeConsolidation.hpp>
00021 #include <crown/CrownException.hpp>
00022 
00023 #include <pelib/AmplInput.hpp>
00024 #include <pelib/Schedule.hpp>
00025 #include <pelib/Scalar.hpp>
00026 #include <pelib/Vector.hpp>
00027 #include <pelib/Matrix.hpp>
00028 #include <pelib/Set.hpp>
00029 #include <pelib/time.h>
00030 
00031 #ifdef debug
00032 #undef debug
00033 #endif
00034 
00035 #define debug(var) cout << "[" << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "] " << #var << " = \"" << (var) << "\"" << endl;
00036 
00037 using namespace std;
00038 using namespace pelib;
00039 using namespace pelib::crown;
00040 
00041 // Quality assessment parameters
00042 static const long long int nsec_in_sec = 1000000000;
00043 
00044 const string CrownCompositeConsolidation::dummyTaskPrefix(DUMMY_TASK);
00045 const string CrownCompositeConsolidation::realTaskPrefix("Real task");
00046 
00047 Algebra
00048 CrownCompositeConsolidation::solve(const Algebra &tg, const Algebra &pt, const pelib::Algebra &param, std::map<const std::basic_string<char>, double> &stats) const
00049 {
00050         float p = pt.find<Scalar<float> >("p")->getValue();
00051         float logp = pow(2, floor(log(p) / log(2)));
00052         
00053         if(p == logp || 1)
00054         {
00055                 Algebra taskgraph = tg;
00056 
00057                 // Get useful problem data
00058                 float n = taskgraph.find<Scalar<float> >("n")->getValue();
00059                 float M = taskgraph.find<Scalar<float> >("M")->getValue();
00060                 map<int, float> work = taskgraph.find<Vector<int, float> >("Tau")->getValues();
00061                 map<int, float> max_width = taskgraph.find<Vector<int, float> >("Wi")->getValues();
00062                 map<int, map<int, float> > efficiency = taskgraph.find<Matrix<int, int, float> >("e")->getValues();
00063 
00064                 // Make mock-up efficiency function for dummy tasks
00065                 map<int, float> dummy_e;
00066                 dummy_e.insert(pair<int, float>(1, 1));
00067                 for(size_t i = 1; i < p; i++)
00068                 {
00069                         dummy_e.insert(pair<int, float>(i + 1, 1e-6));
00070                 }
00071 
00072                 // Make up task names for existing tasks
00073                 map<int, string> name;
00074                 for(size_t i = 0; i < n; i++)
00075                 {
00076                         stringstream ssname;
00077                         ssname << realTaskPrefix << " " << i + 1;
00078                         name.insert(pair<int, string>(i + 1, ssname.str()));
00079                 }
00080 
00081                 // Fill up task with mock-up names, workloads and efficiency
00082                 for(size_t i = 0; i < p - 1; i++)
00083                 {
00084                         stringstream ssname;
00085                         ssname << dummyTaskPrefix << " " << n + i + 1;
00086                         name.insert(pair<int, string>(n + i + 1, ssname.str()));
00087                         work.insert(pair<int, float>(n + i + 1, 0));
00088                         max_width.insert(pair<int, float>(n + i + 1, 1));
00089                         efficiency.insert(pair<int, map<int, float> >(n + i + 1, dummy_e));
00090                 }
00091 
00092                 taskgraph.remove("n");
00093                 taskgraph.remove("Tau");
00094                 taskgraph.remove("Wi");
00095                 taskgraph.remove("e");
00096                 Scalar<float> N("n", n + p - 1);
00097                 Vector<int, float> Tau("Tau", work);
00098                 Vector<int, float> Wi("Wi", max_width);
00099                 Vector<int, string> Name("name", name);
00100                 Matrix<int, int, float> e("e", efficiency);
00101                 taskgraph.insert(&N);
00102                 taskgraph.insert(&Tau);
00103                 taskgraph.insert(&Wi);
00104                 taskgraph.insert(&Name);
00105                 taskgraph.insert(&e);
00106                 
00107                 float max_freq = *pt.find<Set<float> >("F")->getValues().rbegin();
00108 
00109                 // Compute all indices of dummy tasks
00110                 vector<size_t> dummy_index;
00111                 for(size_t i = 0; i < p - 1; i++)
00112                 {
00113                         //stringstream ss;
00114                         //ss << dummyTaskPrefix << " " << i + 1;
00115                         //size_t index = std::distance(tg.getTasks().begin(), tg.getTasks().find(ss.str())) + 1;
00116                         dummy_index.push_back(n + i + 1);               
00117                 }
00118 
00119                 // Get direct access to task workloads
00120                 map<int, float> &dummy_task_workload = (map<int, float>&)taskgraph.find<Vector<int, float> >("Tau")->getValues();
00121 
00122                 // Run Crown binary
00123                 struct timespec start, stop, total_time;
00124                 clock_gettime(CLOCK_MONOTONIC, &start);
00125                 //Algebra best_schedule = crown_binary(schedule, 3);
00126                 Algebra best_schedule = scheduler->solve(taskgraph, pt, param, stats);
00127                 float best_quality = energy_static_dynamic_busy_idle_active(best_schedule);
00128                 //float best_quality = best_schedule.find<Scalar<float> >("quality")->getValue();
00129                 float best_m = best_schedule.find<Scalar<float> >("m")->getValue();
00130                 float m = best_m;
00131                 size_t index = 0;
00132 
00133                 // Increase the number of cores switched off until we reach p cores or
00134                 // until it is not possible to generate any valid schedule anymore
00135                 while(index <= p - 1 && m >= 0)
00136                 {
00137                         // Then we set the dummy tasks' only admissible width to the current number
00138                         // of cores to switch off
00139                         // Set the dummy task workload so that it must run from time 0 to M at max freqeuncy to make the deadline
00140                         dummy_task_workload[n + index + 1] = M * max_freq;
00141 
00142                         // Try to compute a new schedule
00143                         //Algebra current = crown_binary(schedule, 3);
00144                         Algebra current = scheduler->solve(taskgraph, pt, param, stats);
00145 
00146                         // Get the new schedule's quality and correctness
00147                         float quality = energy_static_dynamic_busy_idle_active(current);
00148                         //float quality = current.find<Scalar<float> >("quality")->getValue();
00149                         m = current.find<Scalar<float> >("m")->getValue();
00150 
00151                         // If the new schedule is correct and more energy-efficient that the best schedule
00152                         // the replace the best schedule
00153                         if((m >= 0 || M <= 0) && quality < best_quality)
00154                         {
00155                                 best_schedule = current;
00156                                 best_quality = quality;
00157                                 best_m = m;
00158                         }
00159 
00160                         // Prepare for next task to activate
00161                         index++;
00162                 }
00163 
00164                 clock_gettime(CLOCK_MONOTONIC, &stop);
00165 
00166                 // Remove dummy tasks
00167                 best_schedule.remove("n");
00168                 best_schedule.remove("Tau");
00169                 best_schedule.remove("Wi");
00170                 best_schedule.remove("e");
00171                 best_schedule.remove("name");
00172                 N = Scalar<float>("n", n);
00173                 Tau = Vector<int, float>("Tau", work);
00174                 Wi = Vector<int, float>("Wi", max_width);
00175                 Name = Vector<int, string>("name", name);
00176                 e = Matrix<int, int, float>("e", efficiency);
00177                 best_schedule.insert(tg.find<Scalar<float> >("n"));
00178                 best_schedule.insert(tg.find<Vector<int, float> >("Tau"));
00179                 best_schedule.insert(tg.find<Vector<int, float> >("Wi"));
00180                 best_schedule.insert(tg.find<Matrix<int, int, float> >("e"));
00181 
00182                 // Remove dummy tasks from best_schedule
00183                 map<int, float> grp = best_schedule.find<Vector<int, float> >("group")->getValues();
00184                 map<int, float> freq = best_schedule.find<Vector<int, float> >("frequency")->getValues();
00185                 map<int, float> size = best_schedule.find<Vector<int, float> >("wi")->getValues();
00186                 best_schedule.remove("group");
00187                 best_schedule.remove("frequency");
00188                 best_schedule.remove("wi");
00189                 for(size_t i = 0; i < p - 1; i++)
00190                 {
00191                         grp.erase(grp.find(n + i + 1));
00192                         freq.erase(freq.find(n + i + 1));
00193                         size.erase(size.find(n + i + 1));
00194                 }
00195                 Vector<int, float> group("group", grp);
00196                 Vector<int, float> frequency("frequency", freq);
00197                 Vector<int, float> wi("wi", size);
00198                 best_schedule.insert(&group);
00199                 best_schedule.insert(&frequency);
00200                 best_schedule.insert(&wi);
00201 
00202                 // Report mapping quality
00203                 stats.insert(pair<string, double>("quality", best_quality));
00204 
00205                 // Report optimization time
00206                 float time = (float)(total_time.tv_sec * nsec_in_sec + total_time.tv_nsec) / (float)nsec_in_sec;
00207                 stats.insert(pair<string, double>("time_global", time));
00208 
00209                 return best_schedule;
00210         }
00211         else
00212         {
00213                 throw CrownException("Binary scheduler cannot handle non-power of two number of cores");
00214         }
00215 }
00216 
00217 CrownCompositeConsolidation::CrownCompositeConsolidation(const CrownScheduler *scheduler, bool showOutput, bool showError) : CrownComposite(scheduler, showOutput, showError)
00218 {
00219         /* Do nothing else */
00220 }
00221 
00222 CrownCompositeConsolidation::CrownCompositeConsolidation(const Algebra &param, const CrownScheduler *scheduler, bool showOutput, bool showError) : CrownComposite(param, scheduler, showOutput, showError)
00223 {
00224         /* Do nothing else */
00225 }
00226 
00227 CrownCompositeConsolidation::CrownCompositeConsolidation(const Taskgraph &tg, const Platform &pt, const Algebra &param, const CrownScheduler *scheduler, bool showOutput, bool showError) : CrownComposite(tg, pt, param, scheduler, showOutput, showError)
00228 {
00229         /* Do nothing else */
00230 }
00231 
00232 CrownCompositeConsolidation::CrownCompositeConsolidation(const CrownCompositeConsolidation &src) : CrownComposite(src)
00233 {
00234         /* nothing else to do */
00235 }
00236 
00237 float
00238 CrownCompositeConsolidation::complexity(const Algebra &problem) const
00239 {
00240         return 0;
00241 }
00242 
00243 float
00244 CrownCompositeConsolidation::complexity(const Taskgraph&, const Platform&, const Algebra&) const
00245 {
00246         return 0;
00247 }
00248 
00249 CrownCompositeConsolidation*
00250 CrownCompositeConsolidation::clone() const
00251 {
00252         return new CrownCompositeConsolidation(*this);
00253 }
00254 
00255 Schedule
00256 CrownCompositeConsolidation::schedule(const Taskgraph &tg, const Platform &pt, std::map<const string, double>& stats) const
00257 {
00258         Algebra param = this->param;
00259 
00260         // TODO: Make scheduler work without scalar b
00261         //param.insert(new Scalar<float>("b", 2));
00262         param = param.merge(scheduler->addCrownConfig(tg, pt, param, stats));
00263 
00264         // Take task name out
00265         Algebra taskgraph = tg.buildAlgebra(pt);
00266         Vector<int, string> name = *taskgraph.find<Vector<int, string> >("name");
00267         taskgraph.remove("name");
00268 
00269         //Perform actual work
00270         Algebra schedule = solve(taskgraph, pt.buildAlgebra(), param, stats);
00271 
00272         // Put back task names
00273         schedule.insert(new Vector<int, string>(name));
00274 
00275         // Convert crown schedule to regular algebra schedule
00276         schedule = CrownScheduler::crownToSchedule(schedule);
00277 
00278         // Add task starting time
00279         schedule = Schedule::addStartTime(schedule, tg, pt);
00280 
00281         // report scheduling complexity
00282         float complexity = pt.getCores().size() * crown_binary_complexity(schedule) * (allocation_fastest_complexity(schedule) + mapping_ltlg_complexity(schedule) + frequency_height_complexity(schedule));
00283         stats.insert(pair<string, double>("complexity", complexity));
00284 
00285         float M = tg.getDeadline(pt);
00286         float m = schedule.find<Scalar<float> >("m")->getValue();
00287         Schedule *sched;
00288         if(m < 0 && M > 0)
00289         {
00290                 stats.insert(pair<string, double>("feasible", 0));
00291                 sched = new Schedule(getShortDescription(), tg.getName(), Schedule::table());
00292         }
00293         else
00294         {
00295                 stats.insert(pair<string, double>("feasible", 1));
00296                 string desc = getShortDescription();
00297                 sched = new Schedule(desc, tg.getName(), schedule);
00298         }
00299 
00300         Schedule final = *sched;
00301         delete sched;
00302         return final;
00303 }
00304 
00305 Schedule
00306 CrownCompositeConsolidation::schedule(const Taskgraph &tg, const Platform &pt, const Algebra &param, std::map<const string, double>& stats) const
00307 {
00308         return schedule(tg, pt, stats);
00309 }
00310 
00311 std::string
00312 CrownCompositeConsolidation::getShortDescription() const
00313 {
00314         return string("Cons.") + scheduler->getShortDescription();
00315 }
00316