Commit 454ec507 authored by EYRAUD-DUBOIS Lionel's avatar EYRAUD-DUBOIS Lionel

New general class for Dual Approximation independent algorithms

parent f1851fb4
#ifndef INDEPDP2_H
#define INDEPDP2_H
#include "IndepAllocator.h"
#include "IndepDualGeneric.h"
#include "instance.h"
#include <vector>
extern double lowerBoundTwoResource(Instance& ins, std::vector<int> taskSet,
double CPUload = 0, double GPUload = 0);
class IndepDP2 : public IndepAllocator {
class IndepDP2 : public IndepDualGeneric {
protected:
double tryGuess(Instance &, std::vector<int> taskSet, std::vector<double>& loads,
double maxlen, IndepResult & result, bool getResult);
double epsilon = 0.01;
double discretizationConstant = 3.0;
public:
IndepDP2(const AlgOptions& opt);
IndepResult compute(Instance &, std::vector<int> &taskSet, std::vector<double> &loads);
};
......
......@@ -4,6 +4,7 @@ set(SCHED_SRC
PreAllocatedGreedy.cpp
HeteroPrio.cpp
IndepBalanced.cpp
IndepDualGeneric.cpp ../include/IndepDualGeneric.h
IndepDP2.cpp
IndepImreh.cpp
IndepAccel.cpp
......@@ -15,7 +16,9 @@ set(SCHED_SRC
availSequence.cpp
GreedyAlgorithm.cpp
HeftAlgorithm.cpp
OnlineZhang.cpp ../include/OnlineZhang.h GreedyPerType.cpp ../include/GreedyPerType.h TrueHeteroPrio.cpp ../include/TrueHeteroPrio.h OnlineGeneric.cpp ../include/OnlineGeneric.h OnlineQA.cpp ../include/OnlineQA.h OnlineECT.cpp ../include/OnlineECT.h OnlineERLS.cpp ../include/OnlineERLS.h IndepCLB2C.cpp ../include/IndepCLB2C.h)
OnlineZhang.cpp ../include/OnlineZhang.h GreedyPerType.cpp ../include/GreedyPerType.h TrueHeteroPrio.cpp ../include/TrueHeteroPrio.h OnlineGeneric.cpp ../include/OnlineGeneric.h OnlineQA.cpp ../include/OnlineQA.h OnlineECT.cpp ../include/OnlineECT.h OnlineERLS.cpp ../include/OnlineERLS.h IndepCLB2C.cpp ../include/IndepCLB2C.h
)
if(CPLEX_FOUND)
set(SCHED_SRC ${SCHED_SRC} SchedLPIndep.cpp ../include/SchedLPIndep.h AreaRound.cpp ../include/AreaRound.h)
......
......@@ -9,14 +9,11 @@
using namespace std;
IndepDP2::IndepDP2(const AlgOptions& opt): IndepAllocator(opt) {
verbosity = opt.asInt("verb_DP2", verbosity);
discretizationConstant = opt.asDouble("disc", 3.0);
IndepDP2::IndepDP2(const AlgOptions& opt): IndepDualGeneric(opt) {
discretizationConstant = opt.asDouble("disc", discretizationConstant);
}
// Arbitrary convention: CPU times are index 0, GPU times are index 1. Just a naming thing.
// returns minimum CPU load, taking into account existing loads
double IndepDP2::tryGuess(Instance& instance, std::vector<int> taskSet, vector<double>& loads,
double maxlen, IndepResult &result, bool getResult) {
......@@ -124,160 +121,3 @@ double IndepDP2::tryGuess(Instance& instance, std::vector<int> taskSet, vector<d
return value + existingCPUload;
}
IndepResult IndepDP2::compute(Instance& instance, vector<int> &taskSet, vector<double> &loads) {
if(instance.nbWorkerTypes != 2) {
cerr << "IndepDP2: only implemented for instances with 2 worker types" << endl;
throw(1);
}
IndepResult result(2); // 2 because there are two resource types.
int nbCPU = instance.nbWorkers[0];
int nbGPU = instance.nbWorkers[1];
if(verbosity >= 4) {
cout << "IndepDP2: called with TS=" << taskSet << " and loads=" << loads << endl;
cout << " CPU times: ";
for(int i : taskSet) cout << instance.execType(0, i) << " ";
cout << endl;
cout << " GPU times: ";
for(int i : taskSet) cout << instance.execType(1, i) << " ";
cout << endl;
}
if(taskSet.size() == 0)
return result;
double minload = min(loads[0], loads[1]);
loads[0] -= minload;
loads[1] -= minload;
double low = lowerBoundTwoResource(instance, taskSet, loads[0], loads[1]);
double up = std::numeric_limits<double>::infinity();
// TODO: optim for the case where GPUarea <= min execution time on CPU: result = all on GPU !
/* double firstguess = low;
if(area > low) {
low = area;
firstguess = 1.15*area;
}
bool haveResult = false;
double target = firstguess;
double r = tryGuess(instance, taskSet, target * nbGPU - loads[1], target, result, target == low);
if(verbosity >= 6)
cout << "IndepDP2: firstguess = "<< firstguess << ", result = " << r << " mkspan = " << (r+loads[0])/ nbCPU << endl;
if((r != -1) && (r + loads[0])/nbCPU <= target*(1+ epsilon)) {
up = firstguess;
haveResult = (target == low);
} else {
low = firstguess;
}
*/
double target;
bool haveResult = false;
// Then, dichotomy, as usual
while(abs(up - low) > epsilon*low) {
if(up != std::numeric_limits<double>::infinity())
target = (up + low) / 2;
else
target = 1.15*low;
double r = tryGuess(instance, taskSet, loads, target, result, abs(target - low) <= 3*epsilon*low);
if(verbosity >= 6)
cout << "IndepDP2: TARGET = "<< target << ", result = " << r << " mkspan= " << (r+loads[0])/ nbCPU << endl;
if((r != -1) && (r + loads[0]) /nbCPU <= target * (1+ epsilon)) {
up = target;
haveResult = (abs(target - low) <= 3*epsilon*low);
}
else {
low = target;
}
}
if(! haveResult) {
double r = tryGuess(instance, taskSet, loads, up, result, true);
if(verbosity >= 6)
cout << "IndepDP2: TARGET = "<< up << ", result = " << r << " mkspan= " << (r+loads[0])/ nbCPU << endl;
}
/* if(verbosity >= 4)
cout << "Result of IndepDP2: " << result << endl; */
return result;
}
double lowerBoundTwoResource(Instance& instance, vector<int> taskSet,
double CPUload, double GPUload) {
if(instance.nbWorkerTypes != 2) {
cerr << "lowerBoundTwoResources: only implemented for instances with 2 worker types" << endl;
throw(1);
}
int nbCPU = instance.nbWorkers[0];
int nbGPU = instance.nbWorkers[1];
double longest = 0;
struct TypeData {
int nbTasks;
double CPUtime;
double GPUtime;
double ratio;
};
vector<TypeData> taskTypes(instance.nbTaskTypes);
for(auto &&t: taskSet) {
taskTypes[instance.taskTypes[t]].nbTasks++;
}
for(int i = 0; i < instance.nbTaskTypes; i++) {
TypeData &d = taskTypes[i];
d.CPUtime = instance.execTimes[0][i] / nbCPU;
d.GPUtime = instance.execTimes[1][i] / nbGPU;
d.ratio = instance.execTimes[0][i] / instance.execTimes[1][i];
if(d.nbTasks > 0)
longest = max(longest,
min(instance.execTimes[0][i], instance.execTimes[1][i]));
}
sort(taskTypes.begin(), taskTypes.end(), [&] (TypeData a, TypeData b) {
return (a.ratio > b.ratio);
});
double CPUlen = CPUload / nbCPU, GPUlen = GPUload / nbGPU;
int g = 0; int c = instance.nbTaskTypes - 1;
while(g != c) {
TypeData & d = taskTypes[g]; TypeData &e = taskTypes[c];
if(GPUlen + d.nbTasks * d.GPUtime <= CPUlen + e.nbTasks * e.CPUtime) {
GPUlen += d.nbTasks * d.GPUtime;
g++;
} else {
CPUlen += e.nbTasks * e.CPUtime;
c--;
}
}
TypeData &d = taskTypes[g];
double remCPU = d.nbTasks * d.CPUtime;
double remGPU = d.nbTasks * d.GPUtime;
double area;
if(remCPU + CPUlen <= GPUlen)
area = GPUlen ;
else if(remGPU + GPUlen <= CPUlen)
area = CPUlen;
else
area = (CPUlen*remGPU +remGPU * remCPU + GPUlen * remCPU) / (remCPU + remGPU);
// cout << "LB: " << area << " " << longest << " " << remCPU << " " << remGPU << " " << CPUlen << " " << GPUlen << " " << g << " " << c << endl;
/*for(auto &&t: taskTypes) {
cout << " " << t.nbTasks << " " << t.CPUtime << " " << t.GPUtime <<" " << t.ratio << endl;
} */
return max(area, longest);
}
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