...
 
Commits (6)
......@@ -11,6 +11,10 @@ class IndepDP2 : public IndepDualGeneric {
double tryGuess(Instance &, std::vector<int> taskSet, std::vector<double>& loads,
double maxlen, IndepResult & result, bool getResult);
double discretizationConstant = 3.0;
#ifdef WITH_CPLEX
bool solveWithCplex;
bool cplexUseDiscretizedValues;
#endif
public:
IndepDP2(const AlgOptions& opt);
......
......@@ -13,6 +13,7 @@ class IndepDP3Demi : public IndepDualGeneric {
double discretizationConstant = 3.0;
#ifdef WITH_CPLEX
bool solveWithCplex;
bool cplexUseDiscretizedValues;
#endif
public:
......
......@@ -6,11 +6,23 @@
#include <cmath>
#include "util.h"
#ifdef WITH_CPLEX
#include <ilcplex/ilocplex.h>
ILOSTLBEGIN
#endif
using namespace std;
IndepDP2::IndepDP2(const AlgOptions& opt): IndepDualGeneric(opt) {
discretizationConstant = opt.asDouble("disc", discretizationConstant);
#ifdef WITH_CPLEX
solveWithCplex = (opt.asString("cplex", "false") == "true") || (opt.asString("cplex", "false") == "discrete");
cplexUseDiscretizedValues = opt.asString("cplex", "false") == "discrete";
#else
if(opt.isPresent("cplex"))
cerr << "Warning: DP2: pmtool compiled without cplex support, ignoring 'cplex' option." << endl;
#endif
}
......@@ -35,8 +47,62 @@ double IndepDP2::tryGuess(Instance& instance, std::vector<int> taskSet, vector<d
for(int i = 0; i < instance.nbTaskTypes; i++)
discreteGPUtimings[i] = ceil(instance.execTimes[1][i] / ratio);
const int N = ceil(maxGPUload / ratio);
/* for(auto && t : taskSet)
N += discreteGPUtimings[instance.taskTypes[t]]; */
#ifdef WITH_CPLEX
if(solveWithCplex) {
IloEnv env;
IloModel model = IloModel(env);
IloNumVarArray affect(env, taskSet.size(), 0.0, 1.0, ILOINT); // 0 means on CPU, 1 on GPU
IloExpr totalCPULoad(env);
IloExpr totalGPULoad(env);
for(int i = 0; i < taskSet.size(); ++i) {
int t = taskSet[i];
int taskType = instance.taskTypes[t];
const double exec0 = instance.execTimes[0][taskType];
const double exec1 = instance.execTimes[1][taskType];
totalCPULoad += (1-affect[i])*exec0;
totalGPULoad += affect[i]*(cplexUseDiscretizedValues ? discreteGPUtimings[taskType] : exec1);
}
if(cplexUseDiscretizedValues)
model.add(totalGPULoad <= N);
else
model.add(totalGPULoad <= maxGPUload);
model.add(IloMinimize(env, totalCPULoad));
IloCplex modelCplex = IloCplex(model);
if(verbosity < 8)
modelCplex.setOut(env.getNullStream());
modelCplex.setParam(IloCplex::Param::MIP::Tolerances::MIPGap, 0.000001);
IloBool feasible = modelCplex.solve();
if(! feasible)
return std::numeric_limits<double>::infinity();
double value = modelCplex.getObjValue();
if(getResult) {
result[0].clear();
result[1].clear();
IloNumArray affectValues(env);
modelCplex.getValues(affectValues, affect);
for(int i = 0; i < taskSet.size(); ++i)
if(affectValues[i] > 0.5)
result[1].push_back(i);
else
result[0].push_back(i);
// cout << "CPUResult: " << result[0] << endl;
// cout << "GPUResult: " << result[1] << endl;
}
return value + existingCPUload;
}
#endif
int length = getResult ? taskSet.size() + 1 : 1;
double** CPUload = new double*[length];
CPUload[0] = new double[length * (N+1)];
......@@ -96,12 +162,10 @@ double IndepDP2::tryGuess(Instance& instance, std::vector<int> taskSet, vector<d
}
double value = CPUload[index][N];
if(value == std::numeric_limits<double>::infinity()) {
// Problem not feasible.
return -1;
}
int gLoad = N;
if(getResult) {
if(getResult && value != std::numeric_limits<double>::infinity()) {
result[0].clear();
result[1].clear();
......
......@@ -18,7 +18,8 @@ using namespace std;
IndepDP3Demi::IndepDP3Demi(const AlgOptions& opt): IndepDualGeneric(opt) {
discretizationConstant = opt.asDouble("disc", discretizationConstant);
#ifdef WITH_CPLEX
solveWithCplex = opt.asString("cplex", "false") == "true";
solveWithCplex = (opt.asString("cplex", "false") == "true") || (opt.asString("cplex", "false") == "discrete");
cplexUseDiscretizedValues = opt.asString("cplex", "false") == "discrete";
#else
if(opt.isPresent("cplex"))
cerr << "Warning: DP3demi: pmtool compiled without cplex support, ignoring 'cplex' option." << endl;
......@@ -45,6 +46,17 @@ double IndepDP3Demi::tryGuess(Instance& instance, std::vector<int> taskSet, vect
if(maxGPUload < 0) maxGPUload = 1;
double ratio = target / (discretizationConstant * taskSet.size());
vector<int> discreteGPUtimings(instance.nbTaskTypes);
vector<bool> isLongOnCPU(instance.nbTaskTypes);
vector<bool> isLongOnGPU(instance.nbTaskTypes);
for(int i = 0; i < instance.nbTaskTypes; i++) {
discreteGPUtimings[i] = ceil(instance.execTimes[1][i] / ratio);
isLongOnCPU[i] = instance.execTimes[0][i] > (target/2);
isLongOnGPU[i] = instance.execTimes[1][i] > (target/2);
}
const int N = ceil(maxGPUload / ratio);
#ifdef WITH_CPLEX
if(solveWithCplex) {
IloEnv env;
......@@ -60,22 +72,26 @@ double IndepDP3Demi::tryGuess(Instance& instance, std::vector<int> taskSet, vect
int taskType = instance.taskTypes[t];
const double exec0 = instance.execTimes[0][taskType];
const double exec1 = instance.execTimes[1][taskType];
if(exec0 > target / 2)
if(isLongOnCPU[taskType])
nbTasksWithLargeCPUTime += (1-affect[i]);
if(exec1 > target/2)
if(isLongOnGPU[taskType])
nbTasksWithLargeGPUTime += affect[i];
totalCPULoad += (1-affect[i])*exec0;
totalGPULoad += affect[i]*exec1;
totalGPULoad += affect[i]*(cplexUseDiscretizedValues ? discreteGPUtimings[taskType] : exec1);
}
model.add(nbTasksWithLargeCPUTime <= nbCPU);
model.add(nbTasksWithLargeGPUTime <= nbGPU);
model.add(totalGPULoad <= maxGPUload);
if(cplexUseDiscretizedValues)
model.add(totalGPULoad <= N);
else
model.add(totalGPULoad <= maxGPUload);
model.add(IloMinimize(env, totalCPULoad));
IloCplex modelCplex = IloCplex(model);
if(verbosity <= 8)
if(verbosity < 8)
modelCplex.setOut(env.getNullStream());
modelCplex.setParam(IloCplex::Param::MIP::Tolerances::MIPGap, 0.000001);
IloBool feasible = modelCplex.solve();
if(! feasible)
......@@ -100,10 +116,6 @@ double IndepDP3Demi::tryGuess(Instance& instance, std::vector<int> taskSet, vect
#endif
double ratio = target / (discretizationConstant * taskSet.size());
vector<int> discreteGPUtimings(instance.nbTaskTypes);
for(int i = 0; i < instance.nbTaskTypes; i++)
discreteGPUtimings[i] = ceil(instance.execTimes[1][i] / ratio);
int nbJobsWithLargeCPUTime = 0;
int nbJobsWithLargeGPUTime = 0;
......@@ -115,7 +127,6 @@ double IndepDP3Demi::tryGuess(Instance& instance, std::vector<int> taskSet, vect
++ nbJobsWithLargeGPUTime;
}
const int N = ceil(maxGPUload / ratio);
const int maxMu = min(nbCPU, nbJobsWithLargeCPUTime);
const int maxNu = min(nbGPU, nbJobsWithLargeGPUTime);
const int stateSpaceSize = (N+1) * (maxMu + 1) * (maxNu + 1);
......@@ -146,8 +157,8 @@ double IndepDP3Demi::tryGuess(Instance& instance, std::vector<int> taskSet, vect
const double exec1 = instance.execTimes[1][taskType];
const int discreteGPUtime = discreteGPUtimings[taskType];
const int muOffset = exec0 > (target/2) ? 1 : 0;
const int nuOffset = exec1 > (target/2) ? 1 : 0;
const int muOffset = isLongOnCPU[taskType];
const int nuOffset = isLongOnGPU[taskType];
if(exec0 > target && exec1 > target)
return -1; // Problem is not feasible: task t cannot be placed on any resource
......@@ -168,7 +179,7 @@ double IndepDP3Demi::tryGuess(Instance& instance, std::vector<int> taskSet, vect
}
if(nuOffset) {
for(int l = N; l >= 0; --l) {
getTabValue(CPUload[nextIndex], l, mu, 0) = getTabValue(CPUload[index], l, mu-muOffset, 1) + exec0;
getTabValue(CPUload[nextIndex], l, mu, 0) = getTabValue(CPUload[index], l, mu-muOffset, 0) + exec0;
}
}
}
......@@ -255,10 +266,11 @@ double IndepDP3Demi::tryGuess(Instance& instance, std::vector<int> taskSet, vect
const double exec1 = instance.execTimes[1][taskType];
const int discreteGPUtime = discreteGPUtimings[taskType];
const int muOffset = exec0 > target ? 1 : 0;
const int nuOffset = exec1 > target ? 1 : 0;
const int muOffset = isLongOnCPU[taskType];
const int nuOffset = isLongOnGPU[taskType];
if(getTabValue(CPUload[index], gLoad, mu, nu) == getTabValue(CPUload[index-1], gLoad, mu-muOffset, nu) + exec0) {
if((mu >= muOffset) &&
(abs(getTabValue(CPUload[index], gLoad, mu, nu) - (getTabValue(CPUload[index-1], gLoad, mu-muOffset, nu) + exec0)) <= 1e-5)) {
mu -= muOffset;
result[0].push_back(taskSet[index-1]);
}
......@@ -268,6 +280,13 @@ double IndepDP3Demi::tryGuess(Instance& instance, std::vector<int> taskSet, vect
result[1].push_back(taskSet[index-1]);
}
}
double actualLoad = 0;
for(int & t: result[0])
actualLoad += instance.execTimes[0][instance.taskTypes[t]];
if(abs(actualLoad-value) > 0.0001)
cerr << "DP3Demi Warning: Difference between computed load and actual load: " << value << " " << actualLoad << endl;
}
delete[] CPUload[0];
delete[] CPUload;
......