Commit 82b59474 authored by EYRAUD-DUBOIS Lionel's avatar EYRAUD-DUBOIS Lionel
Browse files

Factorization: List as a child of GreedyAlgorithm now.

  Side effects: remove useless 'chooseTask' member of schedAction
       GreedyAlgorithm now explictely gives priority to workers of lower indices
parent 1f4101ca
......@@ -32,13 +32,6 @@ void ActionSequence::onTaskPush(int t) {
for (std::vector<SchedAction*>::iterator it = actions.begin() ; it != actions.end(); ++it)
(*it)->onTaskPush(t);
}
int ActionSequence::chooseTask(int wType, double now) {
int tmp;
for (std::vector<SchedAction*>::iterator it = actions.begin() ; it != actions.end(); ++it)
if( (tmp = (*it)->chooseTask(wType, now)) != SCHEDACTION_NONE)
return tmp;
return SCHEDACTION_NONE;
}
/* ExportSchedule: exports a schedule */
......
......@@ -7,15 +7,19 @@
#include "instance.h"
#include "algorithm.h"
#include "algoptions.h"
#include "GreedyAlgorithm.h"
class ListAlgorithm : public Algorithm {
class ListAlgorithm : public GreedyAlgorithm {
protected:
RankComputer ranker;
int verbosity;
RankComputer ranker;
TaskSet* readyTasks;
public:
ListAlgorithm(const AlgOptions &options);
double compute(Instance& ins, SchedAction* action);
double compute(Instance& ins, SchedAction* action) override;
int chooseTask(int worker, double now) override;
void onTaskPush(int task, double now) override;
};
#endif
......@@ -11,7 +11,6 @@
class SchedAction {
public:
virtual void onSchedule(int task, int worker, double startTime, double endTime) { }
virtual int chooseTask(int wType, double now) {return SCHEDACTION_NONE; }
virtual void onTaskPush(int task) { }
};
......@@ -24,7 +23,6 @@ class ActionSequence : public SchedAction {
void remove(SchedAction* a);
void onSchedule(int i, int w, double s, double f);
void onTaskPush(int t);
int chooseTask(int wType, double now);
};
class ExportSchedule : public SchedAction {
......
......@@ -26,7 +26,7 @@ double Dmdas::compute(Instance &instance, SchedAction* action) {
}
assignedLoad.resize(instance.totalWorkers, 0);
GreedyAlgorithm::compute(instance, action);
return GreedyAlgorithm::compute(instance, action);
}
// For now keep the "old" version of dmdas where the assigned load also
......
......@@ -7,10 +7,6 @@
using namespace std;
// typedef set<int, rankCompare> rankSet;
GreedyAlgorithm::GreedyAlgorithm(const AlgOptions & options) {
verbosity = options.asInt("verbosity", 0);
doComms = options.asString("comms", "no") == "yes";
......@@ -18,20 +14,18 @@ GreedyAlgorithm::GreedyAlgorithm(const AlgOptions & options) {
double GreedyAlgorithm::compute(Instance& ins, SchedAction* action) {
if(doComms) {
itemManager = new ItemManager(ins);
} else {
itemManager = NULL;
}
// Compute ranks
// TaskSet* readyTasks = ranker.makeSet(ins);
if(doComms) {
itemManager = new ItemManager(ins);
} else {
itemManager = NULL;
}
int nbWorkers = ins.totalWorkers;
int n = ins.nbTasks;
vector< vector<int> > revDependencies = ins.getRevDependencies();
leaveIdle = vector<bool>(nbWorkers, false);
leaveIdle = vector<bool>(nbWorkers, false);
endTimesWorkers = vector<double>(nbWorkers, 0);
nbDep = vector<int>(n, 0);
runningTasks = vector<int>(nbWorkers, -1);
......@@ -41,8 +35,7 @@ double GreedyAlgorithm::compute(Instance& ins, SchedAction* action) {
for(int i = 0; i < n; i++) {
nbDep[i] = ins.dependencies[i].size();
if(nbDep[i] == 0){
// readyTasks->insert(i);
onTaskPush(i, 0);
onTaskPush(i, 0);
if(action != NULL) action->onTaskPush(i);
}
}
......@@ -62,7 +55,6 @@ double GreedyAlgorithm::compute(Instance& ins, SchedAction* action) {
}
int chosenTask = chooseTask(idle, currentTime);
if(chosenTask < 0) {
if(verbosity >= 6)
......@@ -77,17 +69,17 @@ double GreedyAlgorithm::compute(Instance& ins, SchedAction* action) {
cerr << "Greedy: chosenTask is " << chosenTask << " but its dependency " << k << " is not finished" << endl;
throw(1);
}
if(verbosity >= 6)
cout << "Greedy: " << currentTime << " chosen task is #" << chosenTask << ", " << ins.taskIDs[chosenTask] << endl;
double startTime = currentTime;
if(doComms) {
// Compute a finish time which takes communication into account.
// Compute a finish time which takes communication into account.
for(int &item: ins.itemsRequired[chosenTask]) {
int dst = ins.memoryNodes[t][index];
startTime = max(startTime, itemManager->sendItemTo(item, dst, currentTime));
}
int dst = ins.memoryNodes[t][index];
startTime = max(startTime, itemManager->sendItemTo(item, dst, currentTime));
}
}
double finishTime = startTime + ins.execWorker(idle, chosenTask);
......@@ -99,13 +91,13 @@ double GreedyAlgorithm::compute(Instance& ins, SchedAction* action) {
for(int l = 0; l < nbWorkers; l++)
leaveIdle[l] = false;
}
// Is a worker idle now ?
idle = -1;
for(int j = 0; j < nbWorkers; j++)
if((leaveIdle[j] == false) && runningTasks[j] == -1 /*endTimesWorkers[j] <= currentTime*/) {
if(!leaveIdle[j] && runningTasks[j] == -1) {
idle = j;
break;
}
......@@ -116,10 +108,9 @@ double GreedyAlgorithm::compute(Instance& ins, SchedAction* action) {
double nextTime = currentTime;
for(int i = 0; i < nbWorkers; i++){
if(endTimesWorkers[i] > currentTime)
if((idle == -1) || (endTimesWorkers[i] < nextTime))
{
idle = i; nextTime = endTimesWorkers[i];
}
if((idle == -1) || (endTimesWorkers[i] < nextTime)) {
idle = i; nextTime = endTimesWorkers[i];
}
}
if(verbosity >= 6)
cout << "Greedy " << currentTime << " before advancing to " << nextTime << ", idle worker is" << idle << " LI: " << leaveIdle << " ETW: " << endTimesWorkers << endl;
......@@ -131,23 +122,21 @@ double GreedyAlgorithm::compute(Instance& ins, SchedAction* action) {
currentTime = max(currentTime, nextTime);
//Finish all tasks with finishTime <= currentTime
for(int w = 0; w < nbWorkers; w++)
if((runningTasks[w] != -1) && (endTimesWorkers[w] <= currentTime)) {
int i = runningTasks[w];
int index;
int wType = ins.getType(w, &index);
if(verbosity >= 4)
cout << "Greedy: Finishing task " << i << " on worker " << w << " at time " << currentTime << endl;
if(action != NULL)
action->onSchedule(runningTasks[w], w,
endTimesWorkers[w] - ins.execWorker(w, runningTasks[w]), endTimesWorkers[w]);
if(doComms) {
int index;
int wType = ins.getType(w, &index);
for(int& item: ins.itemsProduced[i]) {
int location = ins.memoryNodes[wType][index];
itemManager->produceItemOn(item, location, currentTime);
// cout << ins.itemNames[item] << " " << location << " " << location << " " << currentTime << " " << currentTime << " " << i << endl;
int location = ins.memoryNodes[wType][index];
itemManager->produceItemOn(item, location, currentTime);
}
}
runningTasks[w] = -1;
......@@ -156,15 +145,13 @@ double GreedyAlgorithm::compute(Instance& ins, SchedAction* action) {
throw(1);
}
finishedTasks[i] = true;
nbFinishedTasks ++;
for(int j = 0; j < (int) revDependencies[i].size(); j++) {
int k = revDependencies[i][j];
++nbFinishedTasks;
for(int k: revDependencies[i]) {
nbDep[k]--;
if(verbosity >= 7)
cout << " Dependent task: " << k << " remaining dependencies: " << nbDep[k] << endl;
if(nbDep[k] == 0){
// readyTasks->insert(k);
onTaskPush(k, currentTime);
onTaskPush(k, currentTime);
if(action != NULL) {
action->onTaskPush(k);
}
......@@ -175,25 +162,14 @@ double GreedyAlgorithm::compute(Instance& ins, SchedAction* action) {
for(int l = 0; l < nbWorkers; l++)
leaveIdle[l] = false;
/* Pretty sure I do not need this.
idle = -1;
// Now some worker should be idle.
for(int k = 0; k < ins.nbWorkerTypes; k++){
int wType = wTypeOrdering[k]; int i = wStartIndex[wType];
for(int j = 0; j < ins.nbWorkers[wType]; j++, i++)
if(endtimesWorkers[i] <= currentTime) {
idle = i;
goto afterSecondLoop;
}
}
afterSecondLoop:
if(verbosity >= 4)
cout << "List " << currentTime << " after advancing, idle worker is " << idle << " LI: " << leaveIdle << " ETW: " << endtimesWorkers << endl;
if(idle == -1) {
cerr << "List : no idle worker after advancing time, should not happen" << endl;
throw(1);
}
*/
/* Search for an idle worker again to give priority to lower
indices, not necessarily to the worker that just finished. */
idle = -1;
for(int j = 0; j < nbWorkers; j++)
if((leaveIdle[j] == false) && runningTasks[j] == -1) {
idle = j;
break;
}
}
}
......
......@@ -7,204 +7,32 @@
#include <cmath>
using namespace std;
typedef set<int, rankCompare> rankSet;
ListAlgorithm::ListAlgorithm(const AlgOptions & options):
GreedyAlgorithm(options), ranker(options) {
// vector<double> ListAlgorithm::computeRanks(Instance& ins) {
// vector<double> w;
// if(rankOpt == "heft")
// w = ins.computeHEFTRank();
// else if(rankOpt == "min")
// w = ins.computeMinRank();
// else {
// cerr << "ListAlgorithm: unknown rank " << rankOpt << endl;
// exit(-1);
// }
// return w;
// }
// List of options:
// Rank
//
ListAlgorithm::ListAlgorithm(const AlgOptions & options): ranker(options) {
verbosity = options.asInt("verbosity", 0);
}
static const string listAlgName = "list";
double ListAlgorithm::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<double> endtimesWorkers(nbWorkers, 0);
vector<double> endtimesTasks(n, -1);
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);
}
readyTasks = ranker.makeSet(ins);
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 idle = wStartIndex[wTypeOrdering[0]];
int tasksToSchedule = n;
while(tasksToSchedule > 0) {
int index = 0;
int t = ins.getType(idle, &index);
if(verbosity >= 4) {
cout << "List: " << currentTime << " worker " << idle << " of type " << t << " is idle." << endl;
}
return GreedyAlgorithm::compute(ins, action);
}
int chosenTask = -1;
bool chosenFromFront = false;
if(! readyTasks->empty()) {
if((action != NULL) && ((chosenTask = action->chooseTask(t, currentTime)) != SCHEDACTION_NONE)) {
} else {
chosenTask = readyTasks->front();
chosenFromFront = true;
}
}
int ListAlgorithm::chooseTask(int worker, double now) {
if(chosenTask < 0) {
if(verbosity >= 5)
cout << "List: " << currentTime << " leaving type " << t << " idle." << endl;
leaveIdle[t] = true;
}
if(chosenTask >= 0) {
if(chosenFromFront)
readyTasks->eraseFront();
else
readyTasks->erase(chosenTask);
double finishTime = currentTime + ins.execType(t, chosenTask);
if(verbosity >= 1)
cout << "List: starting " << chosenTask << " of type " << ins.taskTypes[chosenTask] << " at " << currentTime << " to end at " << finishTime << " on worker " << idle << " of type " << t << endl;
tasksToSchedule --;
if(action != NULL)
action->onSchedule(chosenTask, idle, currentTime, finishTime);
if (readyTasks->empty())
return -1;
endtimesWorkers[idle] = finishTime;
endtimesTasks[chosenTask] = finishTime;
}
// Is a worker idle now ?
idle = -1;
for(int k = 0; k < ins.nbWorkerTypes; k++){
int wType = wTypeOrdering[k]; int i = wStartIndex[wType];
for(int j = 0; j < ins.nbWorkers[wType]; j++, i++)
if((leaveIdle[wType] == false) && endtimesWorkers[i] <= currentTime) {
idle = i;
goto afterFirstLoop;
}
}
afterFirstLoop:
if(idle == -1) {
// No worker idle, let us advance time
double nextTime = currentTime;
int i = 0;
for(int k = 0; k < ins.nbWorkerTypes; k++){
for(int j = 0; j < ins.nbWorkers[k]; j++, i++)
if(endtimesWorkers[i] > currentTime)
if((idle == -1) || (endtimesWorkers[i] < nextTime))
{
idle = i; nextTime = endtimesWorkers[i];
}
}
if(verbosity >= 4)
cout << "List " << currentTime << " before advancing, idle worker is" << idle << " LI: " << leaveIdle << " ETW: " << endtimesWorkers << endl;
if(idle == -1) {
cerr << "Found no eligible worker. Ready set size = " << readyTasks->size() << endl;
throw(-1);
}
currentTime = max(currentTime, nextTime);
//Finish all tasks with finishTime <= currentTime
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);
}
}
}
}
int result = readyTasks->front();
readyTasks->eraseFront();
return result;
}
for(int l = 0; l < ins.nbWorkerTypes; l++)
leaveIdle[l] = false;
idle = -1;
// Now some worker should be idle.
for(int k = 0; k < ins.nbWorkerTypes; k++){
int wType = wTypeOrdering[k]; int i = wStartIndex[wType];
for(int j = 0; j < ins.nbWorkers[wType]; j++, i++)
if(endtimesWorkers[i] <= currentTime) {
idle = i;
goto afterSecondLoop;
}
}
afterSecondLoop:
if(verbosity >= 4)
cout << "List " << currentTime << " after advancing, idle worker is " << idle << " LI: " << leaveIdle << " ETW: " << endtimesWorkers << endl;
if(idle == -1) {
cerr << "List : no idle worker after advancing time, should not happen" << endl;
throw(1);
}
}
}
return getMax(endtimesTasks);
void ListAlgorithm::onTaskPush(int task, double now) {
readyTasks->insert(task);
}
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