...
 
Commits (2)
......@@ -14,6 +14,7 @@ class IndepDP3Demi : public IndepDualGeneric {
#ifdef WITH_CPLEX
bool solveWithCplex;
bool cplexUseDiscretizedValues;
int qParameter;
#endif
public:
......
......@@ -20,6 +20,9 @@ IndepDP3Demi::IndepDP3Demi(const AlgOptions& opt): IndepDualGeneric(opt) {
#ifdef WITH_CPLEX
solveWithCplex = (opt.asString("cplex", "false") == "true") || (opt.asString("cplex", "false") == "discrete");
cplexUseDiscretizedValues = opt.asString("cplex", "false") == "discrete";
if(solveWithCplex) {
qParameter = opt.asInt("q", 1);
}
#else
if(opt.isPresent("cplex"))
cerr << "Warning: DP3demi: pmtool compiled without cplex support, ignoring 'cplex' option." << endl;
......@@ -63,29 +66,95 @@ double IndepDP3Demi::tryGuess(Instance& instance, std::vector<int> taskSet, vect
IloModel model = IloModel(env);
IloNumVarArray affect(env, taskSet.size(), 0.0, 1.0, ILOINT); // 0 means on CPU, 1 on GPU
IloExpr nbTasksWithLargeCPUTime(env);
IloExpr nbTasksWithLargeGPUTime(env);
IloExprArray nbTasksWithLargeCPUTime(env, qParameter); // nbTasksWithLargeCPUTime[h-1] is mu_h from the paper.
IloExprArray nbTasksWithLargeGPUTime(env, qParameter); // And this is kappa_h
IloExprArray workOnCPUShelf(env, qParameter); // This is total work of tasks assigned to S_h union S'_h
IloExprArray workOnGPUShelf(env, qParameter);
IloExpr totalCPULoad(env);
IloExpr totalGPULoad(env);
IloExpr totalGPULoad(env);
vector<int> shelfAssignment(taskSet.size(), 0);
for(int h = 0; h < qParameter; ++h) {
nbTasksWithLargeCPUTime[h] = IloExpr(env);
nbTasksWithLargeGPUTime[h] = IloExpr(env);
workOnCPUShelf[h] = IloExpr(env);
workOnGPUShelf[h] = IloExpr(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];
if(isLongOnCPU[taskType])
nbTasksWithLargeCPUTime += (1-affect[i]);
if(isLongOnGPU[taskType])
nbTasksWithLargeGPUTime += affect[i];
const double usedExec1 = (cplexUseDiscretizedValues ? discreteGPUtimings[taskType] : exec1);
for(int h = 1; h <= qParameter; ++h) {
if( (exec0 > (2*qParameter-h)*target/(2*qParameter))
&& ((exec0 <= (2*qParameter-h+1)*target/(2*qParameter))) ) {
// Task belongs to shelf S_h
if(getResult) {
//cerr << "Task " << t << " belongs to CPU shelf " << h << ": exec0=" << exec0 << " thresh=" << (2*qParameter-h)*target/(2*qParameter) << endl;
shelfAssignment[i] = h;
}
nbTasksWithLargeCPUTime[h-1] += (1-affect[i]);
if(h > 1) {
workOnCPUShelf[h-1] += (1-affect[i]) * exec0;
}
}
if( (exec1 > (2*qParameter-h)*target/(2*qParameter))
&& ((h==1) || (exec1 <= (2*qParameter-h+1)*target/(2*qParameter))) ) {
// Task belongs to shelf S_h
// cerr << "Task " << t << " belongs to GPU shelf " << h << endl;
nbTasksWithLargeGPUTime[h-1] += affect[i];
if(h > 1) {
workOnGPUShelf[h-1] += affect[i] * usedExec1;
}
}
}
for(int h = 2; h <= qParameter; ++h) {
if( (exec0 > (h-1)*target/(2*qParameter))
&& (exec0 <= h*target/(2*qParameter)) ) {
// Task belongs to shelf S'_h
// cerr << "Task " << t << " belongs to CPU shelf prime " << h << endl;
workOnCPUShelf[h-1] += (1-affect[i]) * exec0;
shelfAssignment[i] = -h;
}
if( (exec1 > (h-1)*target/(2*qParameter))
&& (exec1 <= h*target/(2*qParameter)) ) {
// Task belongs to shelf S'_h
// cerr << "Task " << t << " belongs to GPU shelf prime " << h << endl;
workOnGPUShelf[h-1] += affect[i] * usedExec1;
}
}
totalCPULoad += (1-affect[i])*exec0;
totalGPULoad += affect[i]*(cplexUseDiscretizedValues ? discreteGPUtimings[taskType] : exec1);
totalGPULoad += affect[i]*usedExec1;
if(exec0 > target)
model.add(affect[i] == 1);
if(exec1 > target)
model.add(affect[i] == 0);
}
model.add(nbTasksWithLargeCPUTime <= nbCPU);
model.add(nbTasksWithLargeGPUTime <= nbGPU);
model.add(IloSum(nbTasksWithLargeCPUTime) <= nbCPU);
model.add(IloSum(nbTasksWithLargeGPUTime) <= nbGPU);
IloExpr sumOfMus(env);
sumOfMus = nbTasksWithLargeCPUTime[0];
IloExpr sumOfKappas(env);
sumOfKappas = nbTasksWithLargeGPUTime[0];
for(int h = 2; h <= qParameter; ++h) {
IloExpr totalWorkOnShelves(env);
for(int l = h; l <= qParameter; ++l)
totalWorkOnShelves += workOnCPUShelf[l-1];
model.add(totalWorkOnShelves <= target * (nbCPU - sumOfMus));
sumOfMus += nbTasksWithLargeCPUTime[h-1];
totalWorkOnShelves = IloExpr(env);
for(int l = h; l <= qParameter; ++l)
totalWorkOnShelves += workOnGPUShelf[l-1];
model.add(totalWorkOnShelves <= target * (nbGPU - sumOfKappas));
sumOfKappas += nbTasksWithLargeGPUTime[h-1];
}
if(cplexUseDiscretizedValues)
model.add(totalGPULoad <= N);
else
......@@ -109,11 +178,35 @@ double IndepDP3Demi::tryGuess(Instance& instance, std::vector<int> taskSet, vect
IloNumArray affectValues(env);
modelCplex.getValues(affectValues, affect);
for(int i = 0; i < taskSet.size(); ++i)
vector<int> shelfNbTasks(qParameter, 0);
vector<int> shelfPossibleTasks(qParameter, 0);
vector<double> shelfLoad(qParameter, 0);
for(int i = 0; i < taskSet.size(); ++i) {
if(shelfAssignment[i] > 0)
shelfPossibleTasks[shelfAssignment[i]-1] += 1;
if(affectValues[i] > 0.5)
result[1].push_back(i);
else
result[0].push_back(i);
result[1].push_back(taskSet[i]);
else {
result[0].push_back(taskSet[i]);
if(shelfAssignment[i] > 0) {
shelfNbTasks[shelfAssignment[i]-1] += 1;
shelfLoad[shelfAssignment[i]-1] += instance.execType(0, taskSet[i]);
}
if(shelfAssignment[i] < 0)
shelfLoad[-shelfAssignment[i]-1] += instance.execType(0, taskSet[i]);
}
}
cout << "shelfNbTasks: " << shelfNbTasks << endl;
cout << "shelfPossTasks: " << shelfPossibleTasks << endl;
cout << "shelf Load: " << shelfLoad << ", total=" << getSum(shelfLoad) << endl;
for(int h = 2; h <= qParameter; ++h) {
int sumOfMus = 0;
double actualLoad = 0;
for(int l = 1; l < h; ++l) sumOfMus += shelfNbTasks[l-1];
for(int l = h; l <= qParameter; ++l) actualLoad += shelfLoad[l-1];
cout << " Constraint " << h << ": sumMus=" << sumOfMus << " load=" << actualLoad << " limit=" << target * (nbCPU - sumOfMus) << " slack=" << target * (nbCPU - sumOfMus) - actualLoad << endl;
}
}
return value + existingCPUload;
}
......