From: Corentin D. <cor...@cr...> - 2011-04-12 16:36:55
|
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 |