crown  1.0.0
src/allocation.cpp
Go to the documentation of this file.
00001 /*
00002  Copyright 2015 Nicolas Melot
00003 
00004  This file is part of Crown.
00005 
00006  Crown is free software: you can redistribute it and/or modify
00007  it under the terms of the GNU General Public License as published by
00008  the Free Software Foundation, either version 3 of the License, or
00009  (at your option) any later version.
00010 
00011  Crown is distributed in the hope that it will be useful,
00012  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00014  GNU General Public License for more details.
00015 
00016  You should have received a copy of the GNU General Public License
00017  along with Crown. If not, see <http://www.gnu.org/licenses/>.
00018 
00019 */
00020 
00021 
00022 #include <fstream>
00023 #include <set>
00024 
00025 #include <cstdlib>
00026 
00027 #include <crown/allocation.h>
00028 
00029 #include <pelib/AmplInput.hpp>
00030 #include <pelib/AmplOutput.hpp>
00031 #include <pelib/Vector.hpp>
00032 #include <pelib/Matrix.hpp>
00033 
00034 #ifdef debug
00035 #undef debug
00036 #endif
00037 #if 0
00038 #define debug(var) cout << "[" << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "] " << #var << " = \"" << var << "\"" << endl;
00039 #else
00040 #define debug(var)
00041 #endif
00042 
00043 using namespace pelib;
00044 using namespace std;
00045 
00046 static const long long int nsec_in_sec = 1000000000;
00047 
00048 static int
00049 timespec_subtract(struct timespec *result, struct timespec *x, struct timespec *y)
00050 {
00051         /* Perform the carry for the later subtraction by updating y. */
00052         if (x->tv_nsec < y->tv_nsec)
00053         {
00054                 int nsec = (y->tv_nsec - x->tv_nsec) / nsec_in_sec + 1;
00055                 y->tv_nsec -= nsec_in_sec * nsec;
00056                 y->tv_sec += nsec;
00057         }
00058         if (x->tv_nsec - y->tv_nsec > nsec_in_sec)
00059         {
00060                 int nsec = (x->tv_nsec - y->tv_nsec) / nsec_in_sec;
00061                 y->tv_nsec += nsec_in_sec * nsec;
00062                 y->tv_sec -= nsec;
00063         }
00064      
00065        /* Compute the time remaining to wait. tv_nsec is certainly positive. */
00066         result->tv_sec = x->tv_sec - y->tv_sec;
00067         result->tv_nsec = x->tv_nsec - y->tv_nsec;
00068      
00069         /* Return 1 if result is negative. */
00070         return x->tv_sec < y->tv_sec;
00071 }
00072 
00073 pelib::Algebra
00074 allocation_fastest(const pelib::Algebra &schedule)
00075 {
00076         Algebra input = schedule;
00077         struct timespec start, stop, total_time;
00078         
00079         // Read tasks's efficiency and decide on their optimal allocation
00080         int p = (int)input.find<Scalar<float> >("p")->getValue();
00081         int b = (int)input.find<Scalar<float> >("b")->getValue();
00082         map<int, float> vector_tau = input.find<Vector<int, float> >("Tau")->getValues();
00083         map<int, map<int, float> > matrix_e = input.find<Matrix<int, int, float> >("e")->getValues();
00084         map<int, float> vector_wi;
00085 
00086         clock_gettime(CLOCK_MONOTONIC, &start); 
00087 
00088         for(map<int, float>::iterator i = vector_tau.begin(); i != vector_tau.end(); i++)
00089         {
00090                 int task = i->first;
00091                 float max_efft = 0;
00092                 int best_p = 0;
00093 
00094                 map<int, float> et = matrix_e[task];
00095                 
00096                 for(map<int, float>::iterator j = et.begin(); j != et.end() && j->first <= p; j++)
00097                 {
00098                         int p = j->first;
00099 
00100                         // Only proceed if p in a power of b
00101                         if(pow(b, floor(log(p) / log(b))) == p)
00102                         {
00103                                 float e = j->second;
00104                                 float efft = p * e;
00105                                 if(max_efft < efft)
00106                                 {
00107                                         max_efft = efft;
00108                                         best_p = p;
00109                                 }
00110                         }
00111                 }
00112                 vector_wi.insert(pair<int, float>(task, best_p));
00113         }
00114 
00115         clock_gettime(CLOCK_MONOTONIC, &stop);
00116         timespec_subtract(&total_time, &stop, &start);
00117         
00118         Scalar<float> *param_time = new Scalar<float>("_total_solve_elapsed_time", (total_time.tv_sec * nsec_in_sec + total_time.tv_nsec) / (float)nsec_in_sec);
00119         input.insert(param_time);
00120 
00121         Vector<int, float> *wi = new Vector<int, float>("wi", vector_wi);
00122         input.insert(wi);
00123 
00124         return input;
00125 }
00126 
00127 Algebra
00128 allocation_random(const Algebra &schedule)
00129 {
00130         Algebra input = schedule;
00131 
00132         struct timespec start, stop, total_time;
00133 
00134         // Read tasks's efficiency and decide on their optimal allocation
00135         int b = (int)input.find<Scalar<float> >("b")->getValue();
00136         int L = (int)(log(input.find<Scalar<float> >("p")->getValue()) / log(b));
00137         map<int, float> vector_Wi = input.find<Vector<int, float> >("Wi")->getValues();
00138         map<int, float> vector_wi;
00139 
00140         clock_gettime(CLOCK_MONOTONIC, &start); 
00141 
00142         for(map<int, float>::iterator i = vector_Wi.begin(); i != vector_Wi.end(); i++)
00143         {
00144                 int task = i->first;
00145                 int Wi = (int)i ->second;
00146 
00147                 Wi = (int)(log(Wi) / log(b));
00148                 Wi = Wi > L ? L : Wi;           
00149                 
00150                 vector_wi.insert(pair<int, float>(task, (float)pow((double)b, (double)(rand() % (Wi + 1)))));
00151         }
00152 
00153         clock_gettime(CLOCK_MONOTONIC, &stop);
00154         timespec_subtract(&total_time, &stop, &start);
00155         Scalar<float> *param_time = new Scalar<float>("_total_solve_elapsed_time", (total_time.tv_sec * nsec_in_sec + total_time.tv_nsec) / (float)nsec_in_sec);
00156         input.insert(param_time);
00157 
00158         Vector<int, float> *wi = new Vector<int, float>("wi", vector_wi);
00159         input.insert(wi);
00160 
00161         return input;
00162 }
00163 
00164 Algebra
00165 allocation_temin(const Algebra &schedule)
00166 {
00167         Algebra input = schedule;
00168         struct timespec start, stop, total_time;
00169         
00170         // Read tasks's efficiency and decide on their optimal allocation
00171         int p = (int)input.find<Scalar<float> >("p")->getValue();
00172         int b = (int)input.find<Scalar<float> >("b")->getValue();
00173         map<int, float> vector_tau = input.find<Vector<int, float> >("Tau")->getValues();
00174         map<int, map<int, float> > matrix_e = input.find<Matrix<int, int, float> >("e")->getValues();
00175         map<int, float> vector_wi;
00176 
00177         // Extract the global threshold scalar, if any, or build one
00178         const Scalar<float> *gemin = input.find<Scalar<float> >("gemin");
00179         if(gemin == NULL)
00180         {
00181                 gemin = new Scalar<float>("gemin", 0.5);
00182                 input.insert(gemin);
00183                 delete gemin;
00184                 gemin = input.find<Scalar<float> >("gemin");
00185         }
00186         
00187         // Extract the threshold vector, if any, or build one
00188         const Vector<int, float> *temin = input.find<Vector<int, float> >("temin");
00189         if(temin == NULL)
00190         {
00191                 map<int, float> t;
00192                 for(map<int, float>::iterator iter = vector_wi.begin(); iter != vector_wi.end(); iter++)
00193                 {
00194                         //cerr << "Task " << iter->first << ", efficiency = " << global_threshold->getValue() << endl;
00195                         t.insert(pair<int, float>(iter->first, gemin->getValue()));
00196                 }
00197 
00198                 temin = new Vector<int, float>("temin", t);
00199                 input.insert(temin);
00200                 delete temin;
00201                 temin = input.find<Vector<int, float> >("temin");
00202         }
00203         map<int, float> map_temin = temin->getValues();
00204 
00205         clock_gettime(CLOCK_MONOTONIC, &start); 
00206 
00207         for(map<int, float>::iterator i = vector_tau.begin(); i != vector_tau.end(); i++)
00208         {
00209                 int task = i->first;
00210                 float max_efft = 0;
00211                 int best_p = 0;
00212                 float emin = map_temin[task];
00213                 //cerr << "# Task " << task << "; emin = " << emin << endl;
00214 
00215                 map<int, float> et = matrix_e[task];
00216                 
00217                 for(map<int, float>::iterator j = et.begin(); j != et.end() && j->first <= p; j++)
00218                 {
00219                         int p = j->first;
00220                         //cerr << "# Task " << task << "; p = " << p << endl;
00221 
00222                         // Only proceed if p in a power of b
00223                         if(pow(b, floor(log(p) / log(b))) == p)
00224                         {
00225                                 float e = j->second;
00226                                 float efft = p * e;
00227                                 //cerr << "# Task " << task << "; p = " << p << "; e = " << e << "; efft = " << efft << "; max_efft = " << max_efft << "; emin = " << emin << endl;
00228                                 if(max_efft < efft && e >= emin)
00229                                 {
00230                                         //cerr << "# Task " << task << "; best_p = " << p << "; max_efft = " << efft << endl;
00231                                         max_efft = efft;
00232                                         best_p = p;
00233                                 }
00234                         }
00235                 }
00236                 vector_wi.insert(pair<int, int>(task, best_p));
00237         }
00238 
00239         clock_gettime(CLOCK_MONOTONIC, &stop);
00240         timespec_subtract(&total_time, &stop, &start);
00241         
00242         Scalar<float> *param_time = new Scalar<float>("_total_solve_elapsed_time", (total_time.tv_sec * nsec_in_sec + total_time.tv_nsec) / (float)nsec_in_sec);
00243         input.insert(param_time);
00244 
00245         Vector<int, float> *wi = new Vector<int, float>("wi", vector_wi);
00246         input.insert(wi);
00247 
00248         cerr << "# Redoing allocation" << endl;
00249 
00250         return input;
00251 }
00252 
00253 Algebra
00254 allocation_gemin(const Algebra &schedule, float gemin)
00255 {
00256         Algebra input = schedule;
00257         struct timespec start, stop, total_time;
00258 
00259         // Read tasks's efficiency and decide on their optimal allocation
00260         int p = (int)input.find<Scalar<float> >("p")->getValue();
00261         int b = (int)input.find<Scalar<float> >("b")->getValue();
00262         map<int, float> vector_tau = input.find<Vector<int, float> >("Tau")->getValues();
00263         map<int, map<int, float> > matrix_e = input.find<Matrix<int, int, float> >("e")->getValues();
00264         map<int, float> vector_wi;
00265 
00266         clock_gettime(CLOCK_MONOTONIC, &start); 
00267 
00268         for(map<int, float>::iterator i = vector_tau.begin(); i != vector_tau.end(); i++)
00269         {
00270                 int task = i->first;
00271                 float max_efft = 0;
00272                 int best_p = 0;
00273 
00274                 map<int, float> et = matrix_e[task];
00275                 
00276                 for(map<int, float>::iterator j = et.begin(); j != et.end() && j->first <= p; j++)
00277                 {
00278                         int p = j->first;
00279 
00280                         // Only proceed if p in a power of b
00281                         if(pow(b, floor(log(p) / log(b))) == p)
00282                         {
00283                                 float e = j->second;
00284                                 float efft = p * e;
00285 
00286                                 //cerr << "e = " << e << "; efft = " << efft << endl;
00287                                 if(max_efft < efft && e >= gemin)
00288                                 {
00289                                         max_efft = efft;
00290                                         best_p = p;
00291                                         //cerr << "max_efft = " << efft << "; best p = " << p << endl;
00292                                 }
00293                         }
00294                 }
00295                 vector_wi.insert(pair<int, int>(task, best_p));
00296         }
00297 
00298         clock_gettime(CLOCK_MONOTONIC, &stop);
00299         timespec_subtract(&total_time, &stop, &start);
00300         
00301         Scalar<float> *param_time = new Scalar<float>("_total_solve_elapsed_time", (total_time.tv_sec * nsec_in_sec + total_time.tv_nsec) / (float)nsec_in_sec);
00302         input.insert(param_time);
00303 
00304         Vector<int, float> *wi = new Vector<int, float>("wi", vector_wi);
00305         input.insert(wi);
00306 
00307         return input;
00308 }
00309 
00310 float
00311 allocation_fastest_complexity(const pelib::Algebra &schedule)
00312 {
00313         float n = schedule.find<Scalar<float> >("n")->getValue();
00314         float p = schedule.find<Scalar<float> >("p")->getValue();
00315 
00316         return n * log(p);
00317 }
00318