Hello,
I'm working in a project that aims to reduce the energy consumption in a
datacenter.
The main idea is to move the Virtual Machines from one server to
another. This allows us to shut down some servers,
reallocate workload to "greener" servers, etc. Until now, we use some
home made algorithms.
But my idea is now to use a constraint programming framework to separate
the constraints from the algorithms...
So I'm trying Choco to see if it's adequate for my problem.
Here is my first try:
/
//Constant declaration
int nbServers = 8; // number of servers
int nbVMs = 8; // number of VMs
// Build the model
CPModel m = new CPModel();
//RAM available on each server
int[] serverRAMs = new int[nbServers];
for(int i = 0; i<nbServers; i++)
serverRAMs[i] = 100;
//RAM used by each VM
int[] vmRAMs = new int[nbVMs];
for(int i = 0; i<nbVMs; i++)
vmRAMs[i] = 50;
//Matrix indicating the server on which to run a VM
IntegerVariable VMservers[][] = new
IntegerVariable[nbServers][nbVMs];
// For each variable, we define its name and the boundaries of
its domain.
for(int i = 0; i<nbServers; i++) {
for(int j = 0; j<nbVMs; j++) {
VMservers[i][j] = makeIntVar("server" + i + "_VM" + j,
0, 1);
// Associate the variable to the model.
//m.addVariable(VMservers[i][j]);
}
}
// server RAM should not be exceeded
for(int i = 0; i<nbServers; i++) {
m.addConstraint(leq(scalar(vmRAMs, VMservers[i]),
serverRAMs[i]));
}
IntegerVariable[][] invertVMservers = new
IntegerVariable[nbVMs][nbServers];
// invert the VM-server Matrix
for(int i = 0; i<nbServers; i++) {
for(int j = 0; j<nbVMs; j++) {
invertVMservers[j][i] = VMservers[i][j];
// Associate the variable to the model.
//m.addVariable(invertVMservers[j][i]);
}
}
// a VM must be on exactly one server
for(int i = 0; i<nbVMs; i++) {
m.addConstraint(occurrence(1, invertVMservers[i], 1));
}
//define totalPower: sum of server powers
IntegerVariable totalPower = makeIntVar("totalPower", 1,
1000000, Options.V_BOUND);
IntegerExpressionVariable[] powers = new
IntegerExpressionVariable[nbServers];
//computing the power of every servers
for(int i = 0; i<nbServers; i++) {
IntegerExpressionVariable sumServer = sum(VMservers[i]);
//the power of a server has a constant overhead (10) plus
an overhead per VM (1) (no VM -> switch off server).
powers[i] = ifThenElse(eq(sumServer, 0), constant(0),
plus(10, sumServer));
}
IntegerExpressionVariable power = sum(powers);
m.addConstraint(eq(power, totalPower));
Solver s = new CPSolver();
s.read(m);
//s.setTimeLimit(3000);
//minimize the power
s.minimize(s.getVar(totalPower), false);
//printout
for(int i = 0; i<nbServers; i++) {
System.out.print("Server " + i + " VMs ");
for(int j = 0; j<nbVMs; j++) {
System.out.print(s.getVar(VMservers[i][j]).getVal() + " ");
}
System.out.print("\n");
}/
In the algorithm above I include only one constraint: the RAM consumed
by the VMs inside a server should not exceed the server RAM capacity.
It is horribly slow: for 4 servers and 4 VMs, it take already several
minutes.
The average number of servers in datacentres can be 500 to 1000, and the
number of VM can be up to 50 per machine...
Seems that the "ifThenElse" part is time consuming.
The basic strategy to minimize energy consumption would be to regroup
the VMs at maximum in some servers,
because servers without VMs can be switched off.
So I have several questions:
- How to orient the search toward this strategy?
- Could you make comments on how to improve the code and get it more
efficient/elegant?
- Is it possible to optimize using an external function (in real life
the power calculation per server is provided by a tier as a java
function) ?
- If the searches included in Choco do not suit my need, could I code my
own and still benefit from the Constraint language provided?
Thank you very much,
Corentin
|