schedulers
1.0.0
|
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 00013 #include <string> 00014 #include <iostream> 00015 #if DUMMY == 0 00016 #include <pelib/SandersSpeck.hpp> 00017 #include <pelib/AmplSolver.hpp> 00018 #include <pelib/Schedule.hpp> 00019 #include <pelib/Scalar.hpp> 00020 #include <pelib/Vector.hpp> 00021 #include <pelib/Matrix.hpp> 00022 #include <pelib/Set.hpp> 00023 #include <pelib/Task.hpp> 00024 #include <pelib/Link.hpp> 00025 #include <pelib/Taskgraph.hpp> 00026 #include <pelib/Platform.hpp> 00027 #include <pelib/CastException.hpp> 00028 #include <pelib/ParseException.hpp> 00029 #include <pelib/AmplOutput.hpp> 00030 #include <pelib/PelibException.hpp> 00031 00032 #endif 00033 00034 #define debug(var) cout << "[" << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "] " << #var << " = \"" << (var) << "\"" << endl; 00035 00036 #define LEN 100 00037 00038 #define TAUTHRESHOLD 0.0001 00039 #define MINFACT 0.0001 00040 00041 // define a constant to simulate infinity 00042 #define MAX_DOUBLE pow(2.0,50.0) 00043 00044 // define a threshold when interval halving shall stop, instead of exact solution 00045 #define THRESHOLD 0.000001 00046 00047 using namespace std; 00048 00049 typedef struct task{ 00050 int idnumber; 00051 double work; 00052 int maxwidth; 00053 int pbar; 00054 double *htab; 00055 char name[LEN]; 00056 } Task; 00057 00058 typedef struct taskset{ 00059 int number; 00060 int maxnumber; 00061 int maxcores; // max. number of cores for which taskset can be scheduled 00062 char name[LEN]; 00063 Task **list; 00064 } Taskset; 00065 00066 typedef struct taskparams{ 00067 Task *ptr; 00068 double frequency; 00069 double start; 00070 double end; 00071 } Taskparams; 00072 00073 typedef struct schedule{ 00074 double makespan; // makespan to be reached 00075 int corecount; // number of cores actually used for scheduling 00076 int fullcorecount; // full number of cores 00077 Taskset *ts; // taskset that schedule refers to 00078 char name[LEN]; 00079 double *loadpercore; // sums up the loads of the tasks mapped to each core 00080 int *taskspercore; // array of how many tasks are mapped to each core 00081 Taskparams *list; // 2-dim array of size corecount*tasksetsize where element [i*tasksetsize+j] points to j-th task on core i 00082 } Schedule; 00083 00084 typedef struct etable{ 00085 Taskset *ts; 00086 int size; 00087 int cores; 00088 double *etab; 00089 } ETable; 00090 00091 double alpha; 00092 00093 // give the workload of a task 00094 // requires details of task implementation 00095 double taskload(Task *t) { return t->work; } 00096 00097 // give an element of the h-table of a task 00098 // requires 0<=p<=pbar 00099 // requires details of task implementation 00100 double taskhtab(Task *t,int p) { return t->htab[p]; } 00101 00102 // init a taskset (given the number of tasks) 00103 // note: does not set the number of tasks 00104 // requires detail of Taskset implementation 00105 void inittaskset(Taskset *ts,int n,char *name,int maxcores) 00106 { 00107 ts->number = 0; 00108 ts->maxnumber = n; 00109 ts->maxcores = maxcores; 00110 strcpy(ts->name,name); 00111 ts->list = (Task**)malloc(sizeof(Task*)*n); 00112 } 00113 00114 double g(int i) { return (double)i*(double)i; } 00115 00116 // specific: the efficiency function is e(0)=1, e(i)=1-R*g(i)/g(maxwidth) for 1<=i<=maxwidth, with g(x)=g^2, and R=0.3 00117 // requires that 1<=i and 1<=maxwidth 00118 double efficiency(int i,int maxwidth) 00119 { double R=0.3; 00120 00121 if(i==1) return 1.0; 00122 else if (i>maxwidth) return 0.000001; 00123 else return 1.0-R*g(i)/g(maxwidth); 00124 } 00125 00126 // compute the table of h function, and pbar for task 00127 void computehtab(Task *t,int maxcores) 00128 { int i; 00129 double eff; 00130 00131 t->pbar=maxcores;// patch for case that real pbar is larger than corecount available! 00132 t->htab=(double*)malloc(sizeof(double)*(1+maxcores)); // one more as htab starts with 0 00133 t->htab[0]=0.0; 00134 for(i=1;i<=maxcores;i++){ 00135 eff=efficiency(i,t->maxwidth); 00136 // h(i)=sqrt[alpha-1](speedup(i)^alpha/i) 00137 // as speedup(i)=eff(i)*i, we get: 00138 t->htab[i]=pow(eff,alpha/(alpha-1.0))*(double)i; 00139 if((t->htab[i])<(t->htab[i-1])) { t->pbar=i-1; break; } 00140 } 00141 } 00142 00143 // add a task to a taskset 00144 // requires detail of Task and Taskset implementation 00145 void addtasktotaskset(Taskset *ts,int id,double work,int maxwidth,char *name) 00146 { 00147 ts->list[ts->number]=(Task*)malloc(sizeof(Task)); 00148 ts->list[ts->number]->idnumber=id; 00149 ts->list[ts->number]->work=work; 00150 ts->list[ts->number]->maxwidth=maxwidth; 00151 strcpy(ts->list[ts->number]->name,name); 00152 computehtab(ts->list[ts->number],ts->maxcores); 00153 ts->number++; 00154 } 00155 00157 // note: does not free the memory for tasks 00158 // requires detail of Taskset implementation 00159 void deinittaskset(Taskset *ts) 00160 { 00161 free(ts->list); 00162 } 00163 00164 // copy a taskset: requires details of taskset implementation 00165 // does not copy the tasks themselves, only the pointers to the tasks 00166 // includes a taskset initialization, i.e. if taskset trg has been initialized before, it should be deinited first 00167 void copytaskset(Taskset *trg,Taskset *src,char *name) 00168 { int i; 00169 00170 inittaskset(trg,src->number,name,src->maxcores); 00171 trg->number = src->number; 00172 for(i=0;i<trg->number;i++) *((trg->list)+i) = *((src->list)+i); 00173 } 00174 00175 #if DUMMY != 0 00176 // dummy, just for testing 00177 // requires detail of Taskset implementation 00178 void readinput(Taskset *ts,int maxcores) 00179 { int taskcount=10; 00180 inittaskset(ts, taskcount, (char*)string("Dummy task set").c_str(), maxcores); 00181 // addtasktotaskset(ts,id,workload,maxwidth,name); 00182 /* addtasktotaskset(ts,0,4.0,8, (char*)string("task 0").c_str()); 00183 addtasktotaskset(ts,1,3.0,6, (char*)string("task 1").c_str()); 00184 addtasktotaskset(ts,2,5.0,4, (char*)string("task 2").c_str()); 00185 addtasktotaskset(ts,3,0.4,3, (char*)string("task 3").c_str()); 00186 addtasktotaskset(ts,4,0.3,2, (char*)string("task 4").c_str()); 00187 addtasktotaskset(ts,5,0.2,1, (char*)string("task 5").c_str()); 00188 */ 00189 addtasktotaskset(ts,0,27.0,4, (char*)string("task 1").c_str()); 00190 addtasktotaskset(ts,1,13.0,4, (char*)string("task 2").c_str()); 00191 addtasktotaskset(ts,2,16.0,4, (char*)string("task 3").c_str()); 00192 addtasktotaskset(ts,3,11.0,1, (char*)string("task 4").c_str()); 00193 addtasktotaskset(ts,4,27.0,4, (char*)string("task 5").c_str()); 00194 addtasktotaskset(ts,5,16.0,4, (char*)string("task 6").c_str()); 00195 addtasktotaskset(ts,6,34.0,4, (char*)string("task 7").c_str()); 00196 addtasktotaskset(ts,7,25.0,4, (char*)string("task 8").c_str()); 00197 addtasktotaskset(ts,8,27.0,4, (char*)string("task 9").c_str()); 00198 addtasktotaskset(ts,9,17.0,4, (char*)string("task 10").c_str()); 00199 } 00200 #else 00201 void readinput(Taskset *ts, const pelib::Taskgraph &tg, const pelib::Platform &arch) 00202 { 00203 using namespace std; 00204 using namespace pelib; 00205 00206 int taskcount = tg.getTasks().size(); 00207 inittaskset(ts, taskcount, (char*)string("taskset as read in").c_str(), arch.getCores().size()); 00208 00209 for(set<pelib::Task>::const_iterator i = tg.getTasks().begin(); i != tg.getTasks().end(); i++) 00210 { 00211 size_t id = std::distance(tg.getTasks().begin(), i); 00212 addtasktotaskset(ts, id, i->getWorkload(), i->getMaxWidth(), (char*) i->getName().c_str()); 00213 } 00214 } 00215 00216 #endif 00217 00218 // return the name string of a taskset 00219 // requires detail of Taskset implementation 00220 char *tasksetname(Taskset *ts) { return ts->name; } 00221 00222 // give number of tasks in taskset 00223 // requires details of taskset implementation 00224 int tssize(Taskset *ts) { return ts->number; } 00225 00227 // requires details of taskset implementation 00228 Task *gettask(Taskset *ts,int i) { return ts->list[i]; } 00229 00230 // print a task 00231 // requires detail of task implementation 00232 void printtask(Task *t) 00233 { int i; 00234 00235 printf("Task %d <%s> work %lf maxwidth %d pbar %d\nh-table:",t->idnumber,t->name,t->work,t->maxwidth,t->pbar); 00236 for(i=0;i<=t->pbar;i++) printf(" %lf",t->htab[i]); 00237 printf("\n"); 00238 } 00239 00240 // print a taskset 00241 // requires detail of taskset implementation 00242 void printtaskset(Taskset *ts) 00243 { int i; 00244 00245 printf("Taskset <%s> for up to %d cores\n",ts->name,ts->maxcores); 00246 for(i=0;i<tssize(ts);i++) printtask(ts->list[i]); 00247 } 00248 00249 //#define fprintf(...) 00250 #define printf_d(expr) fprintf(stderr, "[%s:%s:%d] %s = %d\n", __FILE__, __FUNCTION__, __LINE__, #expr, (int)expr); 00251 #define printf_lf(expr) fprintf(stderr, "[%s:%s:%d] %s = %lf\n", __FILE__, __FUNCTION__, __LINE__, #expr, (double)expr); 00252 double etau(Task *t,int p,double tau,double M) 00253 { double et; 00254 /* 00255 printf_lf(-pow(taskload(t),alpha)) 00256 printf_lf(pow(tau*taskhtab(t,p+1)+(1.0-tau)*taskhtab(t,p),-alpha)) 00257 printf_lf(taskhtab(t,p+1)); 00258 printf_lf(taskhtab(t,p)); 00259 printf_lf(taskhtab(t,p+1)-taskhtab(t,p)); 00260 printf_lf(pow(M, alpha - 1.0)); 00261 */ 00262 00263 et=-pow(taskload(t),alpha)*(alpha-1.0)*pow(tau*taskhtab(t,p+1)+(1.0-tau)*taskhtab(t,p),-alpha)*(taskhtab(t,p+1)-taskhtab(t,p)) / pow(M, alpha - 1.0); 00264 return et; 00265 } 00266 00267 void initetable(ETable *et,Taskset *ts,int cores) 00268 { 00269 et->ts=ts; 00270 et->size=tssize(ts); 00271 et->cores=cores; 00272 et->etab=(double*)malloc(sizeof(double)*(et->size)*(2*cores+1)); 00273 } 00274 00275 void deinitetable(ETable *et) 00276 { 00277 free(et->etab); 00278 } 00279 00280 // requires: cores <= ts->maxcores 00281 // note: all entries are scaled by makespan^{alpha-1} 00282 void computeetable(ETable *et,Taskset *ts,int cores, double M) 00283 { int i,j; 00284 00285 // etable[i*(2*cores+1)+j] gives for task i, element j of its bend points: 00286 // if j is even: E<-(j/2), if j is odd: E->((j+1)/2), i.e. in order: 00287 // E<-(0), E->(1), E<-(1), E->(2),... 00288 // last element is E<-(pbar), i.e. j=2*pbar 00289 initetable(et,ts,cores); 00290 for(i=0;i<tssize(ts);i++){ 00291 et->etab[i*(2*cores+1)]=-MAX_DOUBLE; // E<-(0)=-infinity 00292 for(j=1;j<=2*(gettask(ts,i)->pbar);j++){ 00293 et->etab[i*(2*cores+1)+j]=etau(gettask(ts,i),(j-1)/2,1.0, M); 00294 j++; 00295 et->etab[i*(2*cores+1)+j]=etau(gettask(ts,i),j/2,0.0, M); 00296 } 00297 } 00298 } 00299 00300 void printetable(ETable *et) 00301 { int i,j; 00302 00303 printf("e-table for task set %s\n",et->ts->name); 00304 for(i=0;i<et->size;i++){ 00305 printf("Task %d:",i); 00306 for(j=0;j<1+2*gettask(et->ts,i)->pbar;j++){ 00307 printf(" %lf",et->etab[i*(1+2*(et->cores))+j]); 00308 } 00309 printf("\n"); 00310 } 00311 } 00312 00313 void computeinitialc(Taskset *ts,ETable *et,double *clp,double *cup, double M) 00314 { int i; 00315 int pm; 00316 double taum; 00317 double cl,cltmp,cu,cutmp; 00318 00319 if(tssize(ts)>et->cores){ pm=0; taum=(double)(et->cores)/(double)(tssize(ts)); } else { pm=1; taum=0.0; } 00320 cl=0.0; cu=0.0; 00321 for(i=0;i<tssize(ts);i++){ 00322 cltmp=etau(gettask(ts,i),pm,taum, M); 00323 //printf_lf(cltmp); 00324 if(cltmp<cl) cl=cltmp; 00325 cutmp=et->etab[i*(1+2*(et->cores))+2*(gettask(ts,i)->pbar)]; 00326 if(cutmp<cu) cu=cutmp; 00327 } 00328 00329 *clp=cl; 00330 *cup=cu; 00331 } 00332 00333 double invertefunction(Taskset *ts,ETable *et,int i,double c,double cl,double cu,int *bendpointsleftptr,double M) 00334 { int j; 00335 int pint; 00336 double proc,tau; 00337 00338 // find adjacent bendpoints for c 00339 // in final version, use binary search. Here: linear 00340 for(j=0;j<2*gettask(ts,i)->pbar;j++) 00341 if(c<et->etab[i*(2*(ts->maxcores)+1)+j]) break; 00342 // now know that c is between j-1 and j 00343 // printf("task %d position in etable %d\n",i,j-1); 00344 // check if cl and cu are between bendpoints or not 00345 if(!((cl>et->etab[i*(2*(ts->maxcores)+1)+j-1])&&(cu<et->etab[i*(2*(ts->maxcores)+1)+j]))) (*bendpointsleftptr)++; 00346 00347 // check if case 1 or case 2 00348 if((j-1)&1){ // j-1 is odd 00349 // case 2 00350 proc=(double)(j>>1); 00351 // printf("case 2 p+tau=%lf\n",proc); 00352 }else{ // case 1 00353 pint=(j-1)>>1; 00354 proc=(double)pint; 00355 // simple workaround: linear interpolation 00356 //tau = (c-(et->etab[i*(2*(ts->maxcores)+1)+j-1]))/((et->etab[i*(2*(ts->maxcores)+1)+j])-(et->etab[i*(2*(ts->maxcores)+1)+j-1])); 00357 tau = ((ts->list[i]->work)*pow((1.0-alpha)*((ts->list[i]->htab[1+pint])-(ts->list[i]->htab[pint]))/(c*pow(M,alpha-1.0)),1.0/alpha)-(ts->list[i]->htab[pint]))/((ts->list[i]->htab[1+pint])-(ts->list[i]->htab[pint])); 00358 proc += tau; 00359 // proc += ((ts->list[i]->work)*pow((1.0-alpha)*((ts->list[i]->htab[1+pint])-(ts->list[i]->htab[pint]))/(c*pow(M,alpha-1.0)),1.0/alpha)-(ts->list[i]->htab[pint]))/((ts->list[i]->htab[1+pint])-(ts->list[i]->htab[pint])); 00360 //printf_d(j); 00361 // printf("nominator prefactor %lf\n",(ts->list[i]->work)); 00362 // printf("nominator -(alpha-1)*(h(p+1)-h(p)) %lf\n",(1.0-alpha)*((ts->list[i]->htab[1+pint])-(ts->list[i]->htab[pint]))); 00363 //printf_lf(c); 00364 //printf_lf(alpha); 00365 //printf_lf(M); 00366 // printf("nominator c*M to alpha-1 %lf\n",(c*pow(M,alpha-1.0))); 00367 // printf("nominator 2nd addend %lf\n",-(ts->list[i]->htab[pint])); 00368 // printf("denominator %lf\n",((ts->list[i]->htab[1+pint])-(ts->list[i]->htab[pint]))); 00369 // printf("case 1 p=%d tau=%lf\n",pint,proc-(double)pint); 00370 } 00371 // compute p+tau, and return 00372 00373 return proc; 00374 } 00375 00376 int checktoomany(Taskset *ts,ETable *et,double c,double cl,double cu,int *bendpointsleftptr,double M) 00377 { double m,m2; 00378 int i; 00379 int singletaskbendpointsleft = 0; 00380 00381 *bendpointsleftptr = 0; 00382 m=0.0; 00383 for(i=0;i<tssize(ts);i++){ 00384 m2 = invertefunction(ts,et,i,c,cl,cu,&singletaskbendpointsleft,M); 00385 // printf("Task %d alloc %lf\n",i,m2); 00386 m += m2; 00387 //printf_lf(m); 00388 if(singletaskbendpointsleft) (*bendpointsleftptr)++; 00389 } 00390 if(m>(double)(et->cores)) return 1; else return 0; 00391 } 00392 00393 // JKJK Nov 4, 2014: new function 00394 double computetaskenergy(Task *t,int pistar,double taui,double deadline,double lalpha) 00395 { double energy; 00396 double workload; 00397 double hp,hpplusone; 00398 00399 workload=taskload(t); 00400 if(workload == 0) 00401 { 00402 return 0; 00403 } 00404 else 00405 { 00406 hp=taskhtab(t,pistar); 00407 hpplusone=taskhtab(t,pistar+1); 00408 energy=pow(workload,lalpha)/pow(deadline*(taui*hpplusone+(1.0-taui)*hp),lalpha-1.0); 00409 /* 00410 printf_lf(workload); 00411 printf_lf(t->idnumber); 00412 printf_lf(taui); 00413 printf_lf(pistar); 00414 printf_lf(deadline); 00415 printf_lf(lalpha); 00416 printf_lf(hp); 00417 printf_lf(hpplusone); 00418 printf_lf(energy); 00419 printf_lf(pow(workload,lalpha)); 00420 printf_lf(pow(deadline*(taui*hpplusone+(1.0-taui)*hp),lalpha-1.0)); */ 00421 /* if((pistar ==0) && (taui < TAUTHRESHOLD)) 00422 { 00423 energy = pow(workload, lalpha) / pow(deadline * MINFACT, lalpha - 1.0); 00424 } 00425 else 00426 {*/ 00427 // } 00428 return energy; 00429 } 00430 } 00431 00432 // JKJK Nov 4, 2014: changed function to return value double 00433 #if DUMMY != 0 00434 double computeoptc(Taskset *ts,ETable *et,int p,double M) 00435 #else 00436 double computeoptc(Taskset *ts,ETable *et,int p,double M, double minFreq) 00437 #endif 00438 { double cl,cu,c,prev_cl = 0,prev_cu = 0; 00439 int bendpointsflag; 00440 int i; 00441 int dummy; 00442 double pistar; 00443 double energy; // JKJK Nov 4, 2014: added variable 00444 00445 computeinitialc(ts,et,&cl,&cu, M); 00446 //printf_lf(cl); 00447 //printf_lf(cu); 00448 do{ 00449 c=(cl+cu)/2.0; 00450 //printf_lf(c); 00451 prev_cl = cl; 00452 prev_cu = cu; 00453 if(checktoomany(ts,et,c,cl,cu,&bendpointsflag,M)) cu=c; else cl=c; 00454 // }while(bendpointsflag); // skip break when no bendpoints left in intervall, 00455 // directsolve(); // and skip computing direct solution 00456 // instead: stop when interval cl,cu is sufficiently small, and compute processor allocations from c 00457 // printf("cl %lf cu %lf c %lf fabs(cu - cl) %lf\n",cl,cu,c,fabs(cu-cl)); 00458 }while(fabs(cu-cl)>THRESHOLD && (cl != prev_cl || cu != prev_cu)); 00459 c=cu=cl; // ensure that sum of processor allocations is <= number of cores 00460 // output: number of tasks, number of cores, deadline 00461 // printf("%d %d %lf\n",tssize(ts),p,M); 00462 energy=0.0; // JKJK Nov 4, 2014: added statement 00463 // for each task, compute 00464 for(i=0;i<tssize(ts);i++){ 00465 pistar=invertefunction(ts,et,i,c,cl,cu,&dummy,M); 00466 // for each task: tasknumber, integral number of cores allocated p, fractional number of cores allocated tau,speedup of task with p cores, speedup of task with p+1 cores 00467 //printf("%d %d %lf %lf %lf %lf\n",ts->list[i]->idnumber,(int)pistar,pistar-(int)pistar,ts->list[i]->work,((int)pistar)*efficiency((int)pistar,ts->list[i]->maxwidth),(1+(int)pistar)*efficiency(1+(int)pistar,ts->list[i]->maxwidth)); 00468 // printf("%d %d %lf %lf %lf %lf\n",ts->list[i]->idnumber,(int)pistar,pistar,ts->list[i]->work,((int)pistar)*efficiency((int)pistar,ts->list[i]->maxwidth),(1+(int)pistar)*efficiency(1+(int)pistar,ts->list[i]->maxwidth)); 00469 // JKlatest: add x lines 00470 if(pistar<1.0){ 00471 // double taui=pistar-(int)pistar=pistar (because (int)pistar==0); 00472 // double time=taui*M; 00473 // double frequency=taskload(ts->list[i])/time; 00474 00475 #if DUMMY != 0 && FORCE_MIN_FREQUENCY != 0 00476 int minFreq = 1; 00477 #endif 00478 00479 // If the task's necessary frequency is lower than the minimal frequency given by the platform, then raise it to the minimum 00480 #if FORCE_MIN_FREQUENCY != 0 00481 double frequency=taskload(ts->list[i])/(pistar*M); 00482 if(frequency<minFreq){ 00483 pistar=taskload(ts->list[i])/(minFreq * M); // set frequency to 1.0, makes taui smaller! 00484 } 00485 #endif 00486 } 00487 energy+=computetaskenergy(ts->list[i],(int)pistar,pistar-(int)pistar,M,alpha); // JKJK Nov 4, 2014: added statement 00488 /* printf_lf(i); 00489 printf_lf(pistar); 00490 printf_lf(M); 00491 printf_lf(alpha); 00492 printf_lf(energy);*/ 00493 } 00494 return energy; // JKJK Nov 4, 2014: added statement 00495 } 00496 00497 // Quality assessment parameters 00498 const long long int nsec_in_sec = 1000000000; 00499 00500 static int 00501 timespec_subtract(struct timespec *result, struct timespec *x, struct timespec *y) 00502 { 00503 /* Perform the carry for the later subtraction by updating y. */ 00504 if (x->tv_nsec < y->tv_nsec) 00505 { 00506 int nsec = (y->tv_nsec - x->tv_nsec) / nsec_in_sec + 1; 00507 y->tv_nsec -= nsec_in_sec * nsec; 00508 y->tv_sec += nsec; 00509 } 00510 if (x->tv_nsec - y->tv_nsec > nsec_in_sec) 00511 { 00512 int nsec = (x->tv_nsec - y->tv_nsec) / nsec_in_sec; 00513 y->tv_nsec += nsec_in_sec * nsec; 00514 y->tv_sec -= nsec; 00515 } 00516 00517 /* Compute the time remaining to wait. tv_nsec is certainly positive. */ 00518 result->tv_sec = x->tv_sec - y->tv_sec; 00519 result->tv_nsec = x->tv_nsec - y->tv_nsec; 00520 00521 /* Return 1 if result is negative. */ 00522 return x->tv_sec < y->tv_sec; 00523 } 00524 00525 #if DUMMY == 0 00526 static 00527 pelib::Schedule makeSchedule(const pelib::Taskgraph &tg, const pelib::Platform &arch, std::map<const string, double>& stats) 00528 #else 00529 int main(int argc,char *argv[]) 00530 #endif 00531 { 00532 double M; 00533 int p; 00534 struct timespec start, stop, total_time; 00535 Taskset ts; 00536 ETable et; 00537 00538 // set alpha, important for energy and computation of h-function 00539 alpha = 3.0; 00540 00541 #if DUMMY != 0 00542 // set number of cores and makespan 00543 p = 4; 00544 M = 33.6758; 00545 00546 // read in taskset ts 00547 readinput(&ts, p); 00548 #else 00549 p = arch.getCores().size(); 00550 M = tg.getDeadline(arch); 00551 double minFreq = *(*arch.getCores().begin())->getFrequencies().begin(); 00552 00553 readinput(&ts, tg, arch); 00554 #endif 00555 // printtaskset(&ts); 00556 clock_gettime(CLOCK_MONOTONIC, &start); 00557 computeetable(&et,&ts,p, M); 00558 clock_gettime(CLOCK_MONOTONIC, &stop); 00559 #if DUMMY != 0 00560 double energy = computeoptc(&ts,&et,p,M); 00561 #else 00562 double energy = computeoptc(&ts,&et,p,M,minFreq); 00563 #endif 00564 00565 deinittaskset(&ts); 00566 deinitetable(&et); 00567 00568 #if DUMMY != 0 00569 cerr << "energy = " << energy << endl; 00570 #else 00571 /* 00572 printf_lf(energy); 00573 printf_lf(M); 00574 printf_lf((double)p); 00575 printf_lf(alpha); 00576 */ 00577 double freq = pow(energy / (M * p), 1.0/alpha); 00578 00579 pelib::Task t(string("energy")); 00580 t.setWorkload(energy / pow(freq, alpha)); 00581 t.setEfficiencyString("1"); 00582 t.setMaxWidth(p); 00583 t.setFrequency(freq); 00584 00585 std::map<int, std::map<float, pair<const pelib::Task*, double> > > schedule; 00586 for(int i = 0; i < p; i++) 00587 { 00588 std::map<float, pair<const pelib::Task*, double> > core; 00589 core.insert(std::pair<float, pair<const pelib::Task*, double> >(0, pair<const pelib::Task*, double>(&t, t.getWorkload()))); 00590 00591 schedule.insert(pair<int, std::map<float, pair<const pelib::Task*, double> > >(i + 1, core)); 00592 } 00593 00594 pelib::Schedule pelib_schedule(string("Sanders and Speck"), tg.getName(), schedule); 00595 #endif 00596 00597 #if DUMMY != 0 00598 pelib::Taskgraph newtg; 00599 set<pelib::Task> tasks; 00600 tasks.insert(t); 00601 newtg = pelib::Taskgraph(tasks, set<pelib::Link>()); 00602 newtg.setName("Dummy taskgraph"); 00603 std::ostringstream strs; 00604 strs << M; 00605 std::string str = strs.str(); 00606 newtg.setDeadlineCalculator(strs.str()); 00607 std::ofstream newtg_file(std::string(argv[3]), std::ios::out); 00608 pelib::GraphML().dump(newtg_file, newtg); 00609 newtg_file.close(); 00610 00611 pelib::XMLSchedule().dump(cout, pelib_schedule); 00612 #endif 00613 00614 timespec_subtract(&total_time, &stop, &start); 00615 #if DUMMY != 0 00616 cerr << "energy = " << energy << std::endl; 00617 #else 00618 stats.insert(pair<const string, double>("optimal", 1)); 00619 stats.insert(pair<const string, double>("feasible", isfinite(energy))); 00620 stats.insert(pair<const string, double>("time_global", (float)(total_time.tv_sec * nsec_in_sec + total_time.tv_nsec) / (float)nsec_in_sec)); 00621 #endif 00622 00623 #if DUMMY == 0 00624 if(isfinite(energy)) 00625 { 00626 return pelib_schedule; 00627 } 00628 else 00629 { 00630 return pelib::Schedule(string("Sanders and Speck"), tg.getName(), pelib::Schedule::table()); 00631 } 00632 #else 00633 return isfinite(energy) ? EXIT_SUCCESS : EXIT_FAILURE; 00634 #endif 00635 } 00636 00637 pelib::SandersSpeck::SandersSpeck() 00638 { 00639 // Do nothing 00640 } 00641 00642 pelib::SandersSpeck::SandersSpeck(const Taskgraph &tg, const Platform &pt) 00643 { 00644 this->taskgraph = tg; 00645 this->platform = pt; 00646 } 00647 00648 pelib::Schedule 00649 pelib::SandersSpeck::schedule(const Taskgraph &tg, const Platform &pt, std::map<const string, double>& stats) const 00650 { 00651 return makeSchedule(tg, pt, stats); 00652 } 00653 00654 pelib::Schedule 00655 pelib::SandersSpeck::schedule(const Taskgraph &tg, const Platform &pt, const Algebra ¶m, std::map<const string, double>& stats) const 00656 { 00657 return schedule(tg, pt, stats); 00658 } 00659 00660 const pelib::Algebra* 00661 pelib::SandersSpeck::solve() const 00662 { 00663 std::map<const string, double> stats; 00664 return new pelib::Algebra(schedule(this->taskgraph, this->platform, stats).buildAlgebra()); 00665 } 00666 00667 const pelib::Algebra* 00668 pelib::SandersSpeck::solve(std::map<const string, double> &stats) const 00669 { 00670 return new pelib::Algebra(schedule(this->taskgraph, this->platform, stats).buildAlgebra()); 00671 } 00672 00673 std::string 00674 pelib::SandersSpeck::getShortDescription() const 00675 { 00676 return string("SandersSpeck."); 00677 } 00678 00679 #ifdef __cplusplus 00680 extern "C" { 00681 #endif 00682 00683 const pelib::Schedule* 00684 pelib_schedule(const pelib::Taskgraph &tg, const pelib::Platform &pt, size_t argc, char **argv, std::map<const string, double>& statistics) 00685 { 00686 // Convert solver output to general schedule 00687 pelib::Schedule *sched; 00688 sched = new pelib::Schedule(pelib::SandersSpeck().schedule(tg, pt, statistics)); 00689 00690 return sched; 00691 } 00692 00693 string 00694 pelib_description(size_t argc, char **argv) 00695 { 00696 // Convert solver output to general schedule 00697 string desc; 00698 desc = pelib::SandersSpeck().getShortDescription(); 00699 00700 return desc; 00701 } 00702 00703 void 00704 pelib_delete(pelib::Schedule *sched) 00705 { 00706 delete sched; 00707 } 00708 00709 #ifdef __cplusplus 00710 } 00711 #endif 00712 00713