Commit 1bf781d3 authored by EYRAUD-DUBOIS Lionel's avatar EYRAUD-DUBOIS Lionel

Start reworking

parents
#include "instance.h"
class SchedAction {
public:
virtual void onSchedule(int task, int worker, IloNum startTime, IloNum endTime) { }
virtual int chooseType(int task, int nbReady) {return -1; }
virtual void onTaskPush(int task) { }
};
class Algorithm {
public:
virtual double compute(Instance* instance, SchedAction action) { return -1; }
};
This diff is collapsed.
#ifndefined INSTANCE_H
#define INSTANCE_H
typedef IloArray<IloNumVarArray> NumVarMatrix;
typedef IloArray<IloNumArray> NumMatrix;
typedef IloArray<IloIntVarArray> IntVarMatrix;
typedef IloArray<IloIntArray> IntMatrix;
class Instance {
public:
IloIntArray nbWorkers;
NumMatrix execTimes;
IntMatrix dependencies;
IloIntArray taskTypes; // If empty it means it's an uncompressed instance ?
int nbTasks;
IloEnv env;
// Thos are optional, let's say.
IloArray<string> workerNames;
IloArray<string> taskTypeNames;
IloArray<string> taskIDs;
// Computed afterwards
protected:
IntMatrix revDep;
IloIntArray topOrder;
IntMatrix ancestors;
void doConvertIndices();
void populate(env);
public:
Instance(const char* input_file, int convertIndices, IloEnv env);
void display(int verbosity);
void mergeWorkerTypes(IloIntArray indicesToMerge);
/* Accessors for static analysis */
IloIntArray getTopOrder();
IntMatrix getAncestors();
IntMatrix getRevDependencies();
IloNumArray computeRanks(IloNumArray wbar);
protected:
void updateTopOrder(IloIntArray computed, int i, int* l);
void computeTopOrder();
void computeAncestors();
void computeRevDependencies();
};
class CholeskyInstance : public Instance {
CholeskyInstance(IloEnv env, int n, int nbCPU, int nbGPU, IloNum execTimesCPU[], IloNum execTimesGPU[]);
};
class Instance {
public:
vector<int> nbWorkers;
vector< vector<double> > execTimes;
vector< vector<int> > dependencies;
vector<int> taskTypes;
int nbTasks;
// Those are optional, let's say. To be supported in the next version
/* IloArray<string> workerNames;
IloArray<string> taskTypeNames;
IloArray<string> taskIDs; */
// Computed afterwards
protected:
vector< vector<int> > revDep;
vector<int> topOrder;
vector< vector<int> > ancestors;
// ancestors[i][j] == 1 iff there exists a path from j to i
void doConvertIndices();
public:
Instance(const char* input_file, int convertIndices);
void display(int verbosity);
void mergeWorkerTypes(vector<int> indicesToMerge);
/* Accessors for static analysis */
vector<int> getTopOrder();
vector< vector<int> > getAncestors();
vector< vector<int> > getRevDependencies();
vector<double> computeRanks(vector<double> wbar);
protected:
void updateTopOrder(vector<int> computed, int i, int* l);
void computeTopOrder();
void computeAncestors();
void computeRevDependencies();
};
class CholeskyInstance : public Instance {
CholeskyInstance(int n, int nbCPU, int nbGPU, vector<double> execTimesCPU, vector<double> execTimesGPU);
};
#endif
#include "instance.h"
#include "algorithm.h"
typedef std::set<int, rankCompare> rankSet;
class ListAlgorithm : public Algorithm {
IloNumArray computeRanks(Instance* ins) {
//TODO : add an option, have several possible ranks
IloNumArray w = computeHEFTRank(*ins);
return w;
}
public:
// List of options:
// Rank
//
ListAlgorithm(options) {
}
double compute(Instance* ins, SchedAction *action) {
// Compute ranks
IloNumArray rank = computeRanks(ins);
int nbWorkers = IloSum(ins->nbWorkersPerType);
rankCompare rc(rank);
rankSet readyTasks(rc);
int n = ins->nbTasks;
IloEnv env = ins.env;
IloNumArray endtimesWorkers(env);
IloNumArray endtimesTasks(env);
IloBoolArray leaveIdle(env);
IloBoolArray finishedTasks(env);
IloIntArray nbDep(env, n);
endtimesWorkers.add(nbWorkers, 0);
leaveIdle.add(nbWorkers, false);
endtimesTasks.add(n, -1);
finishedTasks.add(n, false);
int nbTaskTypes = execTimes[0].getSize();
int i, j, k, t;
for(i = 0; i < n; i++) {
nbDep[i] = dependencies[i].getSize();
if(nbDep[i] == 0){
readyTasks.insert(i);
if(action != NULL) action->onTaskPush(i);
}
}
IloNum time = 0;
int idle = 0;
int tasksToSchedule = n;
while(tasksToSchedule > 0) {
int index = 0;
int t = getType(idle, nbWorkersPerType, &index);
auto it = readyTasks.begin();
bool found = false;
for(; it != readyTasks.end(); it++) {
int choice = (action != NULL) ? action->chooseType(*it, readyTasks.size()) : -1;
if((choice == -1) || (choice == t)) {
found = true;
break;
}
}
if (found == false){
leaveIdle[idle] = true;
} else {
int chosenTask = *it;
readyTasks.erase(it);
IloNum finishTime = time + execTimes[t][taskTypes[chosenTask]];
cout << "LIST " << chosenTask << " " << taskTypes[chosenTask] << " " << time << " " << finishTime << " " << idle << " " << t << endl;
tasksToSchedule --;
if(action != NULL)
action->onSchedule(chosenTask, t, index, time, finishTime);
endtimesWorkers[idle] = finishTime;
endtimesTasks[chosenTask] = finishTime;
}
IloNum nextTime = time;
idle = -1;
for(i = 0; i < nbWorkers; i++)
if(leaveIdle[i] == false)
if((idle == -1) || (endtimesWorkers[i] < nextTime)) { idle = i; nextTime = endtimesWorkers[i]; }
if(idle == -1) {
cout << "Found no eligible worker. Ready set size = " << readyTasks.size() << endl;
exit(-1);
}
time = max(time, nextTime);
//Finish all tasks with finishTime <= time
for(i = 0; i < n; i++)
if((!finishedTasks[i]) && (endtimesTasks[i] != -1) && (endtimesTasks[i] <= time)) {
// cout << "[" << time << "] Finishing task " << i << endl;
finishedTasks[i] = true;
for(j = 0; j < revDependencies[i].getSize(); j++) {
int k = revDependencies[i][j];
nbDep[k]--;
// cout << " Dependent task: " << k << " remaining dependencies: " << nbDep[k] << endl;
if(nbDep[k] == 0){
auto r = readyTasks.insert(k);
if(!r.second) {
cout << "Task " << k <<" already present in set" << endl;
exit(-1);
}
int choice = -1;
if(action != NULL) {
action->onTaskPush(i);
choice = action->chooseType(k, readyTasks.size());
}
// cout << "[" << time << "] Pushing task " << k << endl;
if(choice == -1)
for(int l = 0; l < nbWorkers; l++)
leaveIdle[l] = false;
else {
int z = 0;
for(t = 0; t < choice; t++) z += nbWorkersPerType[t];
for(int l = 0; l < nbWorkersPerType[choice]; l++, z++)
leaveIdle[z] = false;
}
}
}
}
}
return IloMax(endtimesTasks);
}
};
#include <time.h>
#include <queue>
#include <list>
#include <vector>
#include <string>
#include <sstream>
#include "instance.h"
#include "heuristic.h"
#include <unistd.h>
using namespace std;
static const int opt_no_convert = 10;
static struct option long_options[] = {
{"input", required_argument, 0, 'i' },
{"verbose", no_argument, 0, 'v' },
{"opt", required_argument, 0, 'o'},
{"no-convert", no_argument, 0, opt_no_convert},
{"alg", required_argument, 0, 'a'},
{"bound", required_argument, 0, 'b'},
{"merge", required_argument, 0, 'g'},
{"save", required_argument, 0, 's'},
{0, 0, 0, 0 }
};
static const optsring = "i:vo:a:b:g:s";
std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim)) {
elems.push_back(item);
}
return elems;
}
std::vector<std::string> split(const std::string &s, char delim) {
std::vector<std::string> elems;
split(s, delim, elems);
return elems;
}
typedef map<string, string> algopt;
typedef pair<Algorithm*, algopt> fullAlg;
typedef pair<Bound*, algopt> fullBound;
// TODO: include in an algOptions class, and
// take proper care of overwriting
string parseOptions(const string& s, algopt &result) {
vector<string> opts = split(s, ':');
auto it = opts.begin();
string name = *it;
for(it++; it < opts.end(); it++) {
vector<string> vals = split(*it, '=');
if(vals.size() > 1)
result.emplace(vals[0], vals[1]);
else
result.emplace(vals[0], "");
}
return name;
}
Algorithm* createAlg(const string& name, cont algopt& options) {
Algorithm* alg == NULL;
if(name == "heft")
alg = new HEFTAlgorithm(options);
if(name == "list")
alg = new ListAlgorithm(options);
if(alg == NULL){
cerr << "Unknown algorithm " << name <<". For a list of algorithms, use --alg list" << endl;
exit(-1);
}
return alg;
}
Bound* createBound(const string& name, cont algopt& options) {
Bound* bound == NULL;
if(name == "DRA")
bound = new DRABound(parsedOptions);
if(name == "DAC")
bound = new DRABound(parsedOptions);
if(bound == NULL){
cerr << "Unknown bound " << name <<". For a list of bounds, use --bound list" << endl;
exit(-1);
}
return bound;
}
map<string, Instance*> mergedInstances;
auto globalMergeOpt = globalOptions.find("merge");
if(globalMergeOpt != globalOptions.end()) {
Instance* mergedInstance = new Instance(instance);
mergedInstance->mergeWorkerTypes();
mergedInstances.emplace(globalMergeOpt.second, mergedInstance);
}
Instance* getMergedInstance(Instance original, string mergeArg) {
auto res = mergedInstances.find(mergeArg);
if(res == mergedInstances.end()) {
Instance* result = new Instance(original);
result->mergeWorkerTypes(split(mergeArg, ','));
mergedInstances.emplace(mergeArg, result);
return result;
} else {
return res->second;
}
}
int main(int argc, char** argv) {
string input_file;
int convertIndices = 1;
// int outputValues = 0;
algopt globalOptions();
int verbosity = 0;
IloIntArray toMerge(env);
string saveFile;
vector<fullAlg> algs;
vector<fullBound> bounds;
// Read command-line parameters
int longindex = 0;
int opt = getopt_long(argc, argv, optstring, long_options, & longindex);
string s_optarg;
while(opt != -1) {
if(optarg)
s_optarg = string(optarg);
switch(opt) {
case 'i': input_file = s_optarg; break;
case 'v': verbosity++; break;
case 'a':
algopt options = algopt(globalOptions);
string name = parseOptions(s_optarg, options);
if(name == "list")
displayAlgList();
else
algs.push_back(make_pair(createAlg(name, options), options));
break;
case 'b':
algopt options = algopt(globalOptions);
string name = parseOptions(s_optarg, options);
if(name == "list")
displayBoundList();
else
bounds.push_back(make_pair(createBound(name, options), options));
break;
case 'g':
globalOptions.emplace("merge", s_optarg);
break;
case 's':
globalOptions.emplace("save", s_optarg);
break;
case opt_no_convert:
convertIndices = 0;
break;
default:
break;
}
}
IloEnv env;
// Read instance
Instance instance(input_file, convertIndices, env);
map<string, Instance*> mergedInstances();
// If global merge options, build the corresponding merge instance
auto globalMergeOpt = globalOptions.find("merge");
if(globalMergeOpt != globalOptions.end()) {
getMergedInstance(instance, globalMergeOpt->second);
}
// Iterate through bound list, execute all
for(auto it = bounds.begin(); it < bounds.end; it++) {
auto opts = (*it).second;
Instance* usedInstance = &instance;
// Do the merge if required, starting from the original instance
auto mergeOpt = opts.find("merge");
if(mergeOpt != opts.end()) {
usedInstance = getMergedInstance(instance, mergeOpt->second);
}
double result = ((*it).first)->compute(*usedInstance);
// TODO: Which name should I use ?
cout << input_file << " " << ((*it).first)->name() << " " << result << endl;
}
// Iterate through algorithm list, execute all
for(auto it = algs.begin(); it < algs.end; it++) {
auto opts = (*it).second;
Instance* usedInstance = &instance;
// Do the merge if required, starting from the original instance
auto mergeOpt = opts.find("merge");
if(mergeOpt != opts.end()) {
usedInstance = getMergedInstance(instance, mergeOpt->second);
}
ActionSequence seq();
auto saveOpt = opts.find("save");
if(saveOpt != opts.end()) {
ExportToFile e(usedInstance, saveOpt->second);
seq.add(&e);
}
(it->first)->compute(*usedInstance, &seq);
// TODO: Which name should I use ?
cout << input_file << " " << ((*it).first)->name() << " " << result.makespan() << endl;
}
return(0);
}
#include "schedAction.h"
class ActionSequence : public SchedAction {
std::vector<SchedAction*> actions;
public:
ActionSequence() {}
void add(SchedAction* a) {
actions.push_back(a);
}
void onSchedule(int i, int w, double s, double f) {
for (std::vector<SchedAction*>::iterator it = actions.begin() ; it != actions.end(); ++it) {
(*it)->onSchedule(i, w, s, f);
}
}
void onTaskPush(int t) {
for (std::vector<SchedAction*>::iterator it = actions.begin() ; it != actions.end(); ++it)
(*it)->onTaskPush(t);
}
int chooseType(int t, int nr) {
int tmp;
for (std::vector<SchedAction*>::iterator it = actions.begin() ; it != actions.end(); ++it)
if( (tmp = (*it)->chooseType(t, nr)) >= 0)
return tmp;
return -1;
}
};
class ExportToFile : public SchedAction {
ofstream output;
Instance* instance;
public:
ExportToFile(string filename, Instance* ins, bool header = false)
: output(filename), instance(ins) {
if(header)
output << "Tid worker taskType start duration end" << endl;
}
void onSchedule(int i, w, double s, double f) {
output << i << " " << w << " " << instance->taskTypes[i] << " "
<< s << (f - s) << f << endl;
}
~ExportToFile() {
output.close();
}
}
class rankCompare {
protected:
IloNumArray r;
bool rev;
rankCompare() {}
public:
rankCompare(IloNumArray rank, bool reverse = false) {
r = rank;
rev = reverse;
}
bool operator() (int a, int b) {
if(rev) {
if(r[b] == r[a])
return b < a;
else return (r[b] < r[a]);
}
if(r[a] == r[b])
return a < b;
else return(r[a] < r[b]);
}
};
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment