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

Added dmdas algorithm

parent 322cb625
......@@ -6,6 +6,7 @@ using namespace std;
DepBound::DepBound(AlgOptions options) {
verbosity = options.asInt("verbosity", 0);
instance = NULL;
}
void DepBound::clear() {
......
#include "Dmdas.h"
#include "listAlgorithm.h"
#include "util.h"
#include <vector>
#include <set>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
Dmdas::Dmdas(const AlgOptions& options):
ranker(options), verbosity(options.asInt("verbosity", 0)) {
}
string Dmdas::name() {
static const string n = "dmdas";
return n;
}
double Dmdas::compute(Instance &ins, SchedAction* action) {
// Compute ranks
TaskSet* readyTasks = ranker.makeSet(ins);
int nbWorkers = ins.totalWorkers;
int n = ins.nbTasks;
vector< vector<int> > revDependencies = ins.getRevDependencies();
vector<TaskSet*> localQueues(nbWorkers);
for(auto && tq: localQueues) {
tq = ranker.makeSet(ins);
}
vector<double> endtimesWorkers(nbWorkers, 0);
vector<double> endtimesTasks(n, -1);
vector<double> assignedLoad(nbWorkers, 0);
// vector<bool> leaveIdle(ins.nbWorkerTypes, false);
vector<bool> finishedTasks(n, false);
vector<int> nbDep(n, 0);
/*
vector<int> wTypeOrdering(ins.nbWorkerTypes);
vector<int> wStartIndex(ins.nbWorkerTypes);
vector<double> aggregateTimings(ins.nbWorkerTypes, 1);
int index = 0;
for(int i = 0; i < ins.nbWorkerTypes; i++) {
wStartIndex[i] = index;
index += ins.nbWorkers[i];
for(int j = 0; j < ins.nbTaskTypes; j++) {
aggregateTimings[i] *= ins.execTimes[i][j];
}
aggregateTimings[i] = pow(aggregateTimings[i], 1.0 / ins.nbTaskTypes);
}
for(int i = 0; i < ins.nbWorkerTypes; i++)
wTypeOrdering[i] = i;
sort(wTypeOrdering.begin(), wTypeOrdering.end(),
[&] (int a, int b) { return aggregateTimings[a] < aggregateTimings[b]; });
if(verbosity >= 6)
cout << "List: wTypeOrdering= " << wTypeOrdering << endl;
*/
for(int i = 0; i < n; i++) {
nbDep[i] = ins.dependencies[i].size();
if(nbDep[i] == 0){
readyTasks->insert(i);
if(action != NULL) action->onTaskPush(i);
}
}
double currentTime = 0;
int tasksToSchedule = n;
// For now keep the "old" version of dmdas where the assigned load also
// counts lower priority tasks
auto getFinishedTime = [&] (int task, int w) {
double s = max(endtimesWorkers[w], currentTime);
return (s + assignedLoad[w]
+ ins.exec(getType(w, ins.nbWorkers, NULL), task));
};
auto getBestWorker = [&] (int task) {
double bestSoFar = getFinishedTime(task, 0);
int bestWorker = 0;
for(int i = 1; i < nbWorkers; i++) {
double t = getFinishedTime(task, i);
if(t < bestSoFar) {
bestSoFar = t; bestWorker = i;
}
}
return bestWorker;
};
auto assignFront = [&] () {
int task = readyTasks->front();
int w = getBestWorker(task);
if(verbosity >= 4) {
cout << "dmdas @ " << currentTime << " assigning task " << task << " to worker " << w << endl;
}
localQueues[w]->insert(task);
assignedLoad[w] += ins.exec(getType(w, ins.nbWorkers, NULL), task);
readyTasks->eraseFront();
};
// int idle = wStartIndex[wTypeOrdering[0]];
while(tasksToSchedule > 0) {
while(!readyTasks->empty())
assignFront();
for(int w = 0; w < nbWorkers; w++) {
if((endtimesWorkers[w] <= currentTime) && (!localQueues[w]->empty())) {
int task = localQueues[w]->front();
int wType = getType(w, ins.nbWorkers, NULL);
double finishTime = currentTime + ins.exec(wType, task);
if(verbosity >= 1)
cout << "dmdas: starting " << task << " of type " << ins.taskTypes[task] << " at " << currentTime << " to end at " << finishTime << " on worker " << w << " of type " << wType << endl;
tasksToSchedule --;
if(action != NULL)
action->onSchedule(task, w, currentTime, finishTime);
localQueues[w]->eraseFront();
assignedLoad[w] -= ins.exec(wType, task);
endtimesWorkers[w] = finishTime;
endtimesTasks[task] = finishTime;
}
}
double nextTime = -1;
for(int w = 0; w < nbWorkers; w++) {
if((endtimesWorkers[w] > currentTime) &&
((endtimesWorkers[w] < nextTime) || (nextTime == -1))) {
nextTime = endtimesWorkers[w];
}
}
if(nextTime == -1){
cerr << "dmdas: next Time == -1 !" << endl;
exit(-1);
}
currentTime = nextTime;
//Finish all tasks with finishTime <= currentTime
// TODO: go through all *workers*, not *tasks*
for(int i = 0; i < n; i++)
if((!finishedTasks[i]) && (endtimesTasks[i] != -1) && (endtimesTasks[i] <= currentTime)) {
if(verbosity >= 1)
cout << "List: Finishing task " << i << " at time " << currentTime << endl;
finishedTasks[i] = true;
for(int j = 0; j < (int) revDependencies[i].size(); j++) {
int k = revDependencies[i][j];
nbDep[k]--;
if(verbosity >= 7)
cout << " Dependent task: " << k << " remaining dependencies: " << nbDep[k] << endl;
if(nbDep[k] == 0){
readyTasks->insert(k);
if(action != NULL) {
action->onTaskPush(k);
}
}
}
}
}
return getMax(endtimesTasks);
}
// class Dmdas_Action : public SchedAction {
// protected:
// vector<TaskSet> allocated;
// vector<double> allocatedLoad;
// Instance& instance;
// vector<double> endtimesWorkers;
// int verbosity;
// public:
// Dmdas_Action(Instance& ins, int verb) :
// allocated(ins.totalWorkers), allocatedLoad(ins.totalWorkers),
// instance(ins),
// endtimesWorkers(ins.totalWorkers, 0), verbosity(verb) {
// }
// void onSchedule(int task, int worker, double start, double end) {
// int t = getType(worker, instance.nbWorkers, NULL);
// allocated[t].erase(find(allocated[t].begin(), allocated[t].end(), task));
// allocatedLoad[t] -= ins.execTimes[ins.taskTypes[task]][t];
// endtimesWorkers[worker] = end;
// }
// void onTaskPush(int task) {
// // choose worker w with min finish time
// // add task to allocated[w]
// }
// int chooseTask(int wType, double now) {
// // Hmm. How do I manage this ? There is no notion of *this* worker
// // in ListAlgorithm ... It's bad, cause I have to do "average
// // load" in that case.
// // Probably easier to recode as an "event-based" algorithm
// // Or just find any idle worker of type wType and give the task
// // in its queue.
// // So:
// // take first worker of type wType with finish time <= now
// // and whose queue is non empty. But that's like so wasteful: listAlgorithm knows ;'(
// }
// }
#ifndef DMDAS_H
#define DMDAS_H
#include "instance.h"
#include "algorithm.h"
#include "algoptions.h"
#include "listAlgorithm.h"
class Dmdas : public Algorithm {
protected:
RankComputer ranker;
int verbosity;
public:
Dmdas(const AlgOptions& options);
double compute(Instance &ins, SchedAction* action);
std::string name();
};
#endif
......@@ -9,10 +9,8 @@ using namespace std;
HybridBound::HybridBound(ModifiableBound *_alg, const AlgOptions &options) :
alg(_alg) {
if(options.isPresent("verbosity"))
verbosity = options.asInt("verbosity");
if(options.isPresent("limit"))
timeLimit = options.asInt("limit");
verbosity = options.asInt("verbosity", 0);
timeLimit = options.asInt("limit", 0);
}
string HybridBound::name() {
......
......@@ -8,7 +8,7 @@ CCOPT = -DIL_STD
CCFLAGS = -Wall -g $(CCOPT)
LNFLAGS=
OBJS = pmtool.o algoptions.o algorithm.o schedAction.o listAlgorithm.o instance.o util.o HeftAlgorithm.o availSequence.o HybridBound.o HeteroPrio.o IndepBased.o IndepDP2.o IndepAccel.o IndepDualHP.o
OBJS = pmtool.o algoptions.o algorithm.o schedAction.o listAlgorithm.o instance.o util.o HeftAlgorithm.o availSequence.o HybridBound.o HeteroPrio.o IndepBased.o IndepDP2.o IndepAccel.o IndepDualHP.o Dmdas.o
CPLEX_OBJS = AreaBound.o DepBound.o IterDepBound.o
......
......@@ -15,22 +15,21 @@
* DONE [#A] Check usefulness of combined GPU view
* TODO [#A] Check Indep implementation
** TODO Check with --no-dep sirocco/Full 4 and 8
* DONE [#A] Check Indep implementation
** DONE Check with --no-dep sirocco/Full 4 and 8
* TODO [#A] Ranking by Area-maximizing
https://people.cs.umass.edu/~rsnbrg/areaSell.pdf
* TODO [#A] Standard schedule format
* TODO [#A] dmda(s) implementation
* TODO [#B] How-To / tutorial
* TODO [#B] Options for autoMerging value / merging.
* DONE [#B] Options for autoMerging value / merging.
** Separate merging for different algorithms not supported. Won't be any time soon.
* TODO [#B] Sensible option declaration.
** Parsing ? not sure.
* TODO [#B] Read directly in .rec format
* TODO [#B] Use actual time instead of estimated when converting from .rec
* TODO [#C] Add data to instances for algorithms to share results
* TODO [#C] Constraint Programming [Not yet]
......@@ -55,7 +55,7 @@ string AlgOptions::parseWithName(const string &line) {
void AlgOptions::parse(const std::string &line) {
vector<string> opts = split(line, ':');
for(string s: opts) {
for(string &s: opts) {
include(s);
}
}
......@@ -70,7 +70,7 @@ vector<AlgOptions> AlgOptions::multiParseWithName(const std::string & line, stri
}
vector<string> vals = split(s, '=');
if(vals.size() == 0) {
for(AlgOptions o: result)
for(AlgOptions & o: result)
o.insert(vals[0], "");
} else {
vector<string> cases = split(vals[1], '/');
......@@ -79,7 +79,7 @@ vector<AlgOptions> AlgOptions::multiParseWithName(const std::string & line, stri
o[vals[0]] = cases[0];
}
for(int i = 1; i < cases.size(); i++) {
for(AlgOptions &o: dup) {
for(AlgOptions & o: dup) {
o[vals[0]] = cases[i];
}
result.insert(result.end(), dup.begin(), dup.end());
......
......@@ -16,6 +16,7 @@
#include "HybridBound.h"
#include "HeteroPrio.h"
#include "IndepBased.h"
#include "Dmdas.h"
#ifdef WITH_CPLEX
#include "AreaBound.h"
......@@ -27,12 +28,14 @@ using namespace std;
static const int opt_no_convert = 10;
static const int opt_no_dependencies = 11;
static const int opt_no_header = 12;
static struct option long_options[] = {
{"verbose", required_argument, 0, 'v' },
{"opt", required_argument, 0, 'o'},
{"no-convert", no_argument, 0, opt_no_convert},
{"no-dep", no_argument, 0, opt_no_dependencies},
{"no-header", no_argument, 0, opt_no_header},
{"alg", required_argument, 0, 'a'},
{"bound", required_argument, 0, 'b'},
{"merge", required_argument, 0, 'g'},
......@@ -62,6 +65,8 @@ void displayAlgList() {
cout << " " << " " << "Options: rank, combFactor" << endl;
cout << "indep" << " " << "Sucessive calls to independent tasks alg" << endl;
cout << " " << " " << "Options: indep, verbosity, rank, style" << endl;
cout << "dmdas" << " " << "Somewhat close to *PU original dmdas" << endl;
cout << " " << " " << "Options: verbosity, rank" << endl;
}
Algorithm* createAlg(const string& name, const AlgOptions& options) {
Algorithm* alg = NULL;
......@@ -73,6 +78,8 @@ Algorithm* createAlg(const string& name, const AlgOptions& options) {
alg = new HeteroPrio(options);
if(name == "indep")
alg = new IndepBased(options);
if(name == "dmdas")
alg = new Dmdas(options);
if(alg == NULL){
cerr << "Unknown algorithm " << name <<". For a list of algorithms, use --alg show" << endl;
displayAlgList();
......@@ -135,6 +142,7 @@ int main(int argc, char** argv) {
string repartitionFile = "";
double mergeTolerance = 0.01;
bool outputNamesRaw = 0;
bool noHeader = false;
set<string> optionKeys;
......@@ -148,7 +156,8 @@ int main(int argc, char** argv) {
if(optarg)
s_optarg = string(optarg);
switch(opt) {
case 'v': globalOptions.emplace("verbosity", s_optarg);
case 'v':
globalOptions.insert("verbosity", s_optarg);
verbosity = stoi(s_optarg);
break;
case 'a':
......@@ -160,7 +169,7 @@ int main(int argc, char** argv) {
else {
for(AlgOptions options: optList) {
algs.push_back(make_pair(createAlg(name, options), options));
for(auto s: options)
for(auto & s: options)
optionKeys.insert(s.first);
}
}
......@@ -174,7 +183,7 @@ int main(int argc, char** argv) {
displayBoundList();
else {
bounds.push_back(make_pair(createBound(name, options), options));
for(auto s: options)
for(auto & s: options)
optionKeys.insert(s.first);
}
break;
......@@ -198,6 +207,9 @@ int main(int argc, char** argv) {
case opt_no_dependencies:
noDependencies = true;
break;
case opt_no_header:
noHeader=true;
break;
case 't':
mergeTolerance = atof(optarg);
break;
......@@ -215,6 +227,14 @@ int main(int argc, char** argv) {
}
if((outputNamesRaw == 0) && (!noHeader)) {
// Output header
cout << "input " << "algorithm ";
for(string s: optionKeys)
cout << s << " ";
cout << "mkspan" << endl;
}
for(string input_file: inputFiles) {
// Read instance
Instance instance(input_file, convertIndices);
......@@ -229,13 +249,6 @@ int main(int argc, char** argv) {
map<string, Instance*> mergedInstances();
if(outputNamesRaw == 0) {
// Output header
cout << "input " << "algorithm ";
for(string s: optionKeys)
cout << s << " ";
cout << "mkspan usage" << endl;
}
// Iterate through bound list, execute all
for(auto it = bounds.begin(); it < bounds.end(); it++) {
......@@ -243,7 +256,7 @@ int main(int argc, char** argv) {
double result = it->first->compute(instance);
string name = buildName(it->first->name(), outputNamesRaw, optionKeys, opts);
cout << input_file << " " << name << " " << result << " " << result * instance.totalWorkers << endl;
cout << input_file << " " << name << " " << result << endl;
}
......@@ -280,7 +293,7 @@ int main(int argc, char** argv) {
globalExport->changeName(buildName(it->first->name(), 1, optionKeys, it->second));
double result = it->first->compute(instance, &seq);
cout << input_file << " " << name << " " << result << " " << result * instance.totalWorkers;
cout << input_file << " " << name << " " << result;
if(utilAnalyser){
if(instance.nbWorkerTypes == 2) {
......
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