From 642324575897a2a75b99c5252ae040ab481ccd31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Klervie=20Tocz=C3=A9?= <klervie.tocze@liu.se> Date: Tue, 14 Jan 2025 10:09:25 +0100 Subject: [PATCH] Final updates before ICPE submission --- Code/src/MixedReality_Optimization.java | 53 ++++++++++---- Code/src/device/EnergyModel.java | 6 ++ Code/src/device/PiecewiseLinear.java | 32 ++++++++ Code/src/system/Network.java | 97 +++++++++++++++++++------ Code/src/utils/Config.java | 8 +- 5 files changed, 153 insertions(+), 43 deletions(-) create mode 100644 Code/src/device/EnergyModel.java create mode 100644 Code/src/device/PiecewiseLinear.java diff --git a/Code/src/MixedReality_Optimization.java b/Code/src/MixedReality_Optimization.java index 2a68030..39800ec 100644 --- a/Code/src/MixedReality_Optimization.java +++ b/Code/src/MixedReality_Optimization.java @@ -22,20 +22,21 @@ public class MixedReality_Optimization { //Parameters for the different studies int numberOfFunctionInstances = 2; Boolean usingUniformLoadDistribution = false; - int standardDeviation = 10; - Boolean linksAreLoaded = true; - Boolean randomStartLocation = false; + int standardDeviation = 30; + Boolean linksAreLoaded = false; + Boolean oneCoreAllocation= true; + Boolean randomStartLocation = true; + Boolean colocationScenario = false; // Note: the colocation scenario is only run if the random start location is not activated String appId = "MR_Service"; // identifier of the application Application application = createApplication(appId); - //TODO Check whether this is still actual System.out.println("Description of the experiment:"); System.out.println("- Number of functions instances: " + numberOfFunctionInstances); if (usingUniformLoadDistribution) - {System.out.println("- Load distribution: NORMAL with std " + standardDeviation);} + {System.out.println("- Load distribution: UNIFORM");} else{ - System.out.println("- Load distribution: UNIFORM"); + System.out.println("- Load distribution: NORMAL with std " + standardDeviation); } System.out.println(" The (mean) load increases by 10% per scenario"); if(linksAreLoaded){ @@ -43,6 +44,11 @@ public class MixedReality_Optimization { }else{ System.out.println("- Load on links: 0%"); } + if(oneCoreAllocation){ + System.out.println("- A function instance is allocated up to one CPU core"); + }else{ + System.out.println("- A function instance is allocated all remaining CPU capacity"); + } if (randomStartLocation) {System.out.println("- Start location: RANDOM ");} else{ @@ -52,20 +58,27 @@ public class MixedReality_Optimization { //Determine startLocation = at which device the request is received. This is the placing device String startLocation; if (randomStartLocation){ - Random randomLoc = new Random(); - Integer randomStart=randomLoc.nextInt(11); - startLocation= "gateway_" + randomStart.toString(); - System.out.println("Random start location is "+startLocation); + System.out.println("Random start location is decided per repetition"); + startLocation=null; //Will be set later in the random case } else{ - //For this scenario the start node is NOT random between scenarios - Integer randomStart=0; - startLocation= "gateway_" + randomStart; - System.out.println("Non random start location is "+startLocation); + if(colocationScenario){ + //For this scenario the start node is NOT random between scenarios + Integer randomStart=0; //Start device of 0 with the current function instance placement enables the possibility of colocation on the requesting device + startLocation= "gateway_" + randomStart; + System.out.println("Non random start location is "+startLocation); + } + else { + //For this scenario the start node is NOT random between scenarios + Integer randomStart=4; + startLocation= "gateway_" + randomStart; + System.out.println("Non random start location is "+startLocation); + } + } System.out.println("Creating the network to be used"); - Network network = new Network(application,startLocation); + Network network = new Network(application,startLocation,oneCoreAllocation); System.out.println("Placing the function instances"); placeFunctionInstances(numberOfFunctionInstances,network.getEdgeDevices()); @@ -80,6 +93,16 @@ public class MixedReality_Optimization { for (int a = 0; a< Config.REPETITION_NUMBER; a++) { System.out.println("Repetition " + a); + //For the random beginning device, we want to change it here + if(randomStartLocation){ + // Get new random beginning device + Random randomLoc = new Random(Config.SEED+a); + Integer randomStart=randomLoc.nextInt(11); + startLocation= "gateway_" + randomStart.toString(); + System.out.println("Random start location is "+startLocation); + network.modifyPlacingDevice(startLocation); + } + //for each utilization scenario for (int i = 0; i < Config.LOAD_SCENARIO_NUMBER; i++) { System.out.println("Utilization scenario " + i); diff --git a/Code/src/device/EnergyModel.java b/Code/src/device/EnergyModel.java new file mode 100644 index 0000000..46efa54 --- /dev/null +++ b/Code/src/device/EnergyModel.java @@ -0,0 +1,6 @@ +package device; + +public interface EnergyModel { + + Double getDynamicPowerForUtilization (Double utilization); +} diff --git a/Code/src/device/PiecewiseLinear.java b/Code/src/device/PiecewiseLinear.java new file mode 100644 index 0000000..d277587 --- /dev/null +++ b/Code/src/device/PiecewiseLinear.java @@ -0,0 +1,32 @@ +package device; + +import utils.Config; + +import static java.lang.Math.floor; + +public class PiecewiseLinear implements EnergyModel{ + + //Power data from Ahvar et al. - Parasilo server + int[] powerPerCore = new int[]{98,148,161,176,178,180,184,200,208,212,215,217,218,221,230,237,241}; + int[] powerDynPerCore =new int[17]; + + public PiecewiseLinear(){ + for (int i=0; i<powerDynPerCore.length;i++){ + powerDynPerCore[i]=powerPerCore[i]-powerPerCore[0]; + } + } + + @Override + public Double getDynamicPowerForUtilization(Double utilization) { + double powerRes=0.0; + if(utilization>=100.0){ + powerRes=powerDynPerCore[powerDynPerCore.length-1]; + } + else{ + int j = (int) floor(utilization* Config.DEFAULT_DEVICE_NB_CORES/100); + powerRes = (powerDynPerCore[j+1]-powerDynPerCore[j])*Config.DEFAULT_DEVICE_NB_CORES*(utilization/100)+((j+1)*powerDynPerCore[j]-j*powerDynPerCore[j+1]); + } + + return powerRes; + } +} diff --git a/Code/src/system/Network.java b/Code/src/system/Network.java index 596a892..b4c524d 100644 --- a/Code/src/system/Network.java +++ b/Code/src/system/Network.java @@ -2,6 +2,8 @@ package system; import application.Application; import device.Device; +import device.EnergyModel; +import device.PiecewiseLinear; import org.apache.commons.math3.util.Pair; import placement.RequestPlacementOutput; import utils.Config; @@ -40,7 +42,11 @@ public class Network { String placingDevice; - public Network(Application applicationConsidered, String placingDevice){ + EnergyModel energyModel; + + Boolean oneCoreAllocation; + + public Network(Application applicationConsidered, String placingDevice, boolean oneCoreAllocation_){ application= applicationConsidered; this.placingDevice=placingDevice; @@ -80,6 +86,9 @@ public class Network { createNetworkGraph(); dijkstraAlg = new DijkstraShortestPath<>(graph); + + energyModel = new PiecewiseLinear(); + oneCoreAllocation=oneCoreAllocation_; } private void createNetworkGraph(){ @@ -173,13 +182,14 @@ public class Network { Double currentUtilization = utilization.get(device); //Get size to be calculated Double size = application.getTargetFunctionCPUSize(functionInstance); - //Get available capacity - Double availableCapacity = Config.DEFAULT_DEVICE_CAPACITY * (1-(currentUtilization / 100));//Note: this is allocating all the available capacity + //Get capacity allocated to the function instance + Double allocatedCapacity=getAllocatedCapacity(currentUtilization); + //Calculate according to formula - if (availableCapacity==0){ + if (allocatedCapacity==0){ deviceTiming=Double.valueOf(Config.INFINITE); }else { - deviceTiming = (size / availableCapacity); + deviceTiming = (size / allocatedCapacity); } //Add to the Map variable time_devices.put(device+"-"+functionInstance, deviceTiming); @@ -187,6 +197,23 @@ public class Network { return deviceTiming; } + private Double getAllocatedCapacity(Double currentUtilization){ + //Get available capacity + Double availableCapacity = Config.DEFAULT_DEVICE_CAPACITY_PER_CORE*Config.DEFAULT_DEVICE_NB_CORES * (1-(currentUtilization / 100)); + + //A function instance gets up to one core of capacity or the full remaining capacity + Double allocatedCapacity=0.0; + if(availableCapacity-Config.DEFAULT_DEVICE_CAPACITY_PER_CORE >=0 && oneCoreAllocation){ + //At least one core is available, we allocate one core + allocatedCapacity= (double) Config.DEFAULT_DEVICE_CAPACITY_PER_CORE; + } + else{ + //We allocate what is available + allocatedCapacity=availableCapacity; + } + return allocatedCapacity; + } + private double calculateWeight(Device source, Device destination){ //For this scenario the weight is the latency calculated as the distance between the nodes divided by 100 double distance = calculateDistance(source.getLocationInformation(),destination.getLocationInformation())/100; @@ -226,12 +253,12 @@ public class Network { return totalLatency; } - private double getDynamicPowerForUtilization(double utilizationWithServicePlaced, double dynPower){ + /*private double getDynamicPowerForUtilization(double utilizationWithServicePlaced, double dynPower){ //We consider a linear model were the dynamic power part is 0 at 0% utilization (OBS it still has idle power but this is another constant) // and Dyn power att 100% utilization //utilization in percentage return dynPower*(utilizationWithServicePlaced/100); - } + }*/ //TODO Move to a new Linear energy model class public double getLinkEnergyConsumption(String startFunctionInstanceName, String destinationFunctionInstanceName, String startLocation, String destinationLocation){ @@ -354,10 +381,16 @@ public class Network { //Get Pidle int p_device_idle = Config.DEFAULT_DEVICE_P_IDLE; - //GetPdyn - int p_device_dyn = Config.DEFAULT_DEVICE_P_DYN; + + //Calculate utilization after allocation + double utilizationAfterAllocation = calculateUtilizationAfterAllocation(deviceName); + //Calculate energy - energy_consumption = p_device_idle * deviceTiming + p_device_dyn * deviceTiming; //Assumes 100% utilization when selected + energy_consumption = p_device_idle * deviceTiming + energyModel.getDynamicPowerForUtilization(utilizationAfterAllocation) * deviceTiming; + + if(energy_consumption <0){ + System.out.println("PRoblem"); + } //Add to Map variables energy_devices.put(functionInstanceName, energy_consumption); @@ -365,15 +398,25 @@ public class Network { return energy_consumption; } + private double calculateUtilizationAfterAllocation(String device){ + Double currentUtilization = utilization.get(device); + Double allocatedCapacity = getAllocatedCapacity(currentUtilization); + + //Calculate share of utilization of this allocated capacity + Double allocatedUtilization= allocatedCapacity/(Config.DEFAULT_DEVICE_CAPACITY_PER_CORE*Config.DEFAULT_DEVICE_NB_CORES)*100; //In percentage + + return currentUtilization+allocatedUtilization; + } + public double getInstanceMarginalEnergyConsumption(String functionInstanceName){ // 1- Getting the hardware name Pair<String, String> nameSplit = Utils.splitLongFunctionInstanceName(functionInstanceName); String deviceName = nameSplit.getKey(); //Check whether we already have info about this - double energy_residual_consumption; + double energy_marginal_consumption; if(energy_residual_devices.get(functionInstanceName)!=null){ - energy_residual_consumption=energy_residual_devices.get(functionInstanceName); + energy_marginal_consumption =energy_residual_devices.get(functionInstanceName); }else{ //We need to calculate it @@ -382,24 +425,25 @@ public class Network { //Get Pidle int p_device_idle = Config.DEFAULT_DEVICE_P_IDLE; - //GetPdyn - int p_device_dyn = Config.DEFAULT_DEVICE_P_DYN; + + //Calculate utilization after allocation + double utilizationAfterAllocation = calculateUtilizationAfterAllocation(deviceName); + //Get utilization value for this device Double beforeUtilization = utilization.get(deviceName); if (beforeUtilization == 0) { - energy_residual_consumption = p_device_idle * deviceTiming + p_device_dyn * deviceTiming; //Assumes the utilization gets up to 100% + energy_marginal_consumption = p_device_idle * deviceTiming + energyModel.getDynamicPowerForUtilization(utilizationAfterAllocation) * deviceTiming; } else { - double utilizationWithServicePlaced = 100.0; //Assumption, see above - double utilizationIncrease = utilizationWithServicePlaced - beforeUtilization; - //OBS Assumes a linear power consumption model - double p_device_dyn_util = getDynamicPowerForUtilization(utilizationIncrease, p_device_dyn);//How much power does the utilization increase due to the placement requires? - energy_residual_consumption = p_device_dyn_util * deviceTiming; //Only the dynamic part + //How much power does the utilization increase due to the placement requires? + double powerIncrease = energyModel.getDynamicPowerForUtilization(utilizationAfterAllocation) - energyModel.getDynamicPowerForUtilization(beforeUtilization); + + energy_marginal_consumption = powerIncrease * deviceTiming; //Only the dynamic part } //Add to Map variables - energy_residual_devices.put(functionInstanceName, energy_residual_consumption); + energy_residual_devices.put(functionInstanceName, energy_marginal_consumption); } - return energy_residual_consumption; + return energy_marginal_consumption; } public void evaluatePlacementOutput(RequestPlacementOutput output, String startLocationMathematical, String endLocationMathematical){ @@ -509,7 +553,7 @@ public class Network { energyResLinkDevice = energyResLink + energyResDevice; //Print the results in a usable way - System.out.println("Evaluated placement: Time " + timeLinkDevice + " Energy " + energyLinkDevice + " Residual energy " + energyResLinkDevice + "In details - time link "+ timeLink + " time device " + timeDevice + " energy link " + energyLink + " energy device " + energyDevice + " energy res link "+energyResLink + " energy res device "+energyResDevice); + System.out.println("Evaluated placement: Completion time " + timeLinkDevice + " Overall energy " + energyLinkDevice + " Marginal energy " + energyResLinkDevice + " In details - completion time link "+ timeLink + " completion time device " + timeDevice + " overall energy link " + energyLink + " overall energy device " + energyDevice + " marginal energy link "+energyResLink + " marginal energy device "+energyResDevice); } } @@ -540,7 +584,7 @@ public class Network { //Devices List<String> deviceNames = new ArrayList<>(); for (Device device : edgeDevices) { - if (device.getName().contains("gateway")) {//TODO: with current setup should be all of them so function not needed + if (device.getName().contains("gateway")) {//Note: with current setup should be all of them so this is only to double check deviceNames.add(device.getName()); } } @@ -597,4 +641,9 @@ public class Network { public List<Device> getEdgeDevices(){ return edgeDevices; } + + // Used for the random beginning device case + public void modifyPlacingDevice(String newPlacingDevice){ + this.placingDevice=newPlacingDevice; + } } diff --git a/Code/src/utils/Config.java b/Code/src/utils/Config.java index 2a30df4..a5f2d37 100644 --- a/Code/src/utils/Config.java +++ b/Code/src/utils/Config.java @@ -2,13 +2,13 @@ package utils; public class Config { public static final int LOAD_SCENARIO_NUMBER = 11; - public static final int REPETITION_NUMBER = 25; + public static final int REPETITION_NUMBER = 40; public static final int DEFAULT_LINK_CAPACITY =500;//MBytes/sec public static final int DEFAULT_LINK_P_IDLE =1; public static final int DEFAULT_LINK_P_DYN =9; - public static final int DEFAULT_DEVICE_CAPACITY =500;//MI - public static final int DEFAULT_DEVICE_P_IDLE =98;//W - Data fron Ahvar - Parasilo zero core was 750 - public static final int DEFAULT_DEVICE_P_DYN =148;//W - Data fron Ahvar - Parasilo one core was 250 + public static final int DEFAULT_DEVICE_CAPACITY_PER_CORE =500;//MI + public static final int DEFAULT_DEVICE_P_IDLE =98;//W - Data from Ahvar - Parasilo zero core + public static final int DEFAULT_DEVICE_NB_CORES =16;// Data from Ahvar - Parasilo public static final int INFINITE = 10000;//Very big number so that link/devices with 100% utilization are discarded as impossible public static final int SEED = 165746; } -- GitLab