能耗编程
如何使用CloudSimPlus进行能耗仿真呢?下面通过简单案例进行学习。
主要步骤
-
设置数据中心的更新间隔。
定义更新的时间间隔以保留主机 CPU 利用率历史记录。间隔越大,准确性越低。
使用函数:
setSchedulingInterval()
Datacenter.setSchedulingInterval(SCHEDULING_INTERVAL).
-
设置能耗模型。
基类
PowerModel
是一个接口类。其下有许多子类,例如:PowerModelHost
、PowerModelDatacenter
等。此外,还提供了实现类:
PowerModelHostSimple
等。可以使用默认实现或者自定义。 -
设置可以记录CPU状态。
因为需要根据CPU的利用率来计算能耗。
host.enableUtilizationStats():
它迭代所有现有的虚拟机,启用对每个虚拟机的统计计算。但请记住,当创建主机时,它没有虚拟机。因此,如果您在模拟之前启用计算,则需要为每个虚拟机调用此方法 启动并执行 VM 放置。vm.enableUtilizationStats():
如果为放置 VM 的主机启用统计信息,则会自动为该主机上的每个 VM 启用统计信息。
实例
-
设置间隔
private Datacenter createDatacenterSimple() { for(int i = 0; i < HOSTS; i++) { Host host = createPowerHost(i); hostList.add(host); } final Datacenter dc = new DatacenterSimple(simulation, hostList, new VmAllocationPolicySimple()); dc.setSchedulingInterval(SCHEDULING_INTERVAL); return dc; }
-
设置能耗模型与记录CPU状态
private Host createPowerHost(final int id) { final List<Pe> peList = new ArrayList<>(HOST_PES); //List of Host's CPUs (Processing Elements, PEs) for (int i = 0; i < HOST_PES; i++) { peList.add(new PeSimple(1000, new PeProvisionerSimple())); } final PowerModelHost powerModel = new PowerModelHostSimple(MAX_POWER, STATIC_POWER); final long ram = 2048; //in Megabytes final long bw = 10000; //in Megabits/s final long storage = 1000000; //in Megabytes final ResourceProvisioner ramProvisioner = new ResourceProvisionerSimple(); final ResourceProvisioner bwProvisioner = new ResourceProvisionerSimple(); final VmScheduler vmScheduler = new VmSchedulerTimeShared(); final Host host = new HostSimple(ram, bw, storage, peList); host .setRamProvisioner(ramProvisioner) .setBwProvisioner(bwProvisioner) .setVmScheduler(vmScheduler) .setPowerModel(powerModel); host.setId(id); host.enableUtilizationStats(); return host; }
-
输出结果
private void printHostCpuUtilizationAndPowerConsumption(final Host host) { final HostResourceStats cpuStats = host.getCpuUtilizationStats(); final double utilizationPercentMean = cpuStats.getMean(); final double watts = host.getPowerModel().getPower(utilizationPercentMean); System.out.printf("Host %2d CPU Usage mean: %6.1f%% | Power Consumption mean: %8.0f W%n", host.getId(), utilizationPercentMean * 100, watts); }
实例代码
public class PowerExample1 {
private static final int SCHEDULING_INTERVAL = 10;
private static final int HOSTS = 1;
private static final int HOST_PES = 4;
private static final int VMS = 1;
private static final int VM_PES = 2;
private static final int CLOUDLETS = 10;
private static final int CLOUDLET_PES = 2;
private static final int CLOUDLET_LENGTH = 50000;
/**
* Defines the power a Host uses, even if it's idle (in Watts).
*/
private static final double STATIC_POWER = 35;
/**
* The max power a Host uses (in Watts).
*/
private static final int MAX_POWER = 50;
private final CloudSim simulation;
private DatacenterBroker broker0;
private List<Vm> vmList;
private List<Cloudlet> cloudletList;
private Datacenter datacenter0;
private final List<Host> hostList;
public static void main(String[] args) {
new PowerExample1();
}
private PowerExample1() {
Log.setLevel(Level.WARN);
simulation = new CloudSim();
hostList = new ArrayList<>(HOSTS);
datacenter0 = createDatacenterSimple();
broker0 = new DatacenterBrokerSimple(simulation);
vmList = createVms();
cloudletList = createCloudlets();
broker0.submitVmList(vmList);
broker0.submitCloudletList(cloudletList);
simulation.start();
System.out.println("------------------------------- SIMULATION FOR SCHEDULING INTERVAL = " + SCHEDULING_INTERVAL+" -------------------------------");
final List<Cloudlet> finishedCloudlets = broker0.getCloudletFinishedList();
final Comparator<Cloudlet> hostComparator = comparingLong(cl -> cl.getVm().getHost().getId());
finishedCloudlets.sort(hostComparator.thenComparing(cl -> cl.getVm().getId()));
new CloudletsTableBuilder(finishedCloudlets).build();
printHostsCpuUtilizationAndPowerConsumption();
}
private void printHostsCpuUtilizationAndPowerConsumption() {
System.out.println();
for (final Host host : hostList) {
printHostCpuUtilizationAndPowerConsumption(host);
}
System.out.println();
}
private void printHostCpuUtilizationAndPowerConsumption(final Host host) {
final HostResourceStats cpuStats = host.getCpuUtilizationStats();
// The total Host's CPU utilization for the time specified by the map key
final double utilizationPercentMean = cpuStats.getMean();
final double watts = host.getPowerModel().getPower(utilizationPercentMean);
System.out.printf("Host %2d CPU Usage mean: %6.1f%% | Power Consumption mean: %8.0f W%n", host.getId(), utilizationPercentMean * 100, watts);
}
private Datacenter createDatacenterSimple() {
for(int i = 0; i < HOSTS; i++) {
Host host = createPowerHost(i);
hostList.add(host);
}
final Datacenter dc = new DatacenterSimple(simulation, hostList, new VmAllocationPolicySimple());
dc.setSchedulingInterval(SCHEDULING_INTERVAL);
return dc;
}
private Host createPowerHost(final int id) {
final List<Pe> peList = new ArrayList<>(HOST_PES);
//List of Host's CPUs (Processing Elements, PEs)
for (int i = 0; i < HOST_PES; i++) {
peList.add(new PeSimple(1000, new PeProvisionerSimple()));
}
final PowerModelHost powerModel = new PowerModelHostSimple(MAX_POWER, STATIC_POWER);
final long ram = 2048; //in Megabytes
final long bw = 10000; //in Megabits/s
final long storage = 1000000; //in Megabytes
final ResourceProvisioner ramProvisioner = new ResourceProvisionerSimple();
final ResourceProvisioner bwProvisioner = new ResourceProvisionerSimple();
final VmScheduler vmScheduler = new VmSchedulerTimeShared();
final Host host = new HostSimple(ram, bw, storage, peList);
host.setRamProvisioner(ramProvisioner)
.setBwProvisioner(bwProvisioner)
.setVmScheduler(vmScheduler)
.setPowerModel(powerModel);
host.setId(id);
host.enableUtilizationStats();
return host;
}
private List<Vm> createVms() {
final List<Vm> list = new ArrayList<>(VMS);
for (int i = 0; i < VMS; i++) {
Vm vm = new VmSimple(i, 1000, VM_PES);
vm.setRam(512)
.setBw(1000)
.setSize(10000)
.setCloudletScheduler(new CloudletSchedulerSpaceShared());
vm.enableUtilizationStats();
list.add(vm);
}
return list;
}
private List<Cloudlet> createCloudlets() {
final List<Cloudlet> list = new ArrayList<>(CLOUDLETS);
final UtilizationModel utilization = new UtilizationModelDynamic(0.2);
for (int i = 0; i < CLOUDLETS; i++) {
// Sets half of the cloudlets with the defined length and the other half with the double of it
final long length = i < CLOUDLETS / 2 ? CLOUDLET_LENGTH : CLOUDLET_LENGTH * 2;
Cloudlet cloudlet =
new CloudletSimple(i, length, CLOUDLET_PES)
.setFileSize(1024)
.setOutputSize(1024)
.setUtilizationModelCpu(new UtilizationModelFull())
.setUtilizationModelRam(utilization)
.setUtilizationModelBw(utilization);
list.add(cloudlet);
}
return list;
}
}
仿真结果
------------------------------- SIMULATION FOR SCHEDULING INTERVAL = 10 -------------------------------
SIMULATION RESULTS
Cloudlet|Status |DC|Host|Host PEs |VM|VM PEs |CloudletLen|CloudletPEs|StartTime|FinishTime|ExecTime
ID| |ID| ID|CPU cores|ID|CPU cores| MI| CPU cores| Seconds| Seconds| Seconds
-----------------------------------------------------------------------------------------------------
0|SUCCESS| 1| 0| 4| 0| 2| 50000| 2| 0| 50| 50
1|SUCCESS| 1| 0| 4| 0| 2| 50000| 2| 50| 100| 50
2|SUCCESS| 1| 0| 4| 0| 2| 50000| 2| 100| 150| 50
3|SUCCESS| 1| 0| 4| 0| 2| 50000| 2| 151| 200| 50
4|SUCCESS| 1| 0| 4| 0| 2| 50000| 2| 201| 250| 50
5|SUCCESS| 1| 0| 4| 0| 2| 100000| 2| 251| 351| 100
6|SUCCESS| 1| 0| 4| 0| 2| 100000| 2| 351| 451| 100
7|SUCCESS| 1| 0| 4| 0| 2| 100000| 2| 451| 551| 100
8|SUCCESS| 1| 0| 4| 0| 2| 100000| 2| 552| 651| 100
9|SUCCESS| 1| 0| 4| 0| 2| 100000| 2| 652| 751| 100
-----------------------------------------------------------------------------------------------------
Host 0 CPU Usage mean: 45.5% | Power Consumption mean: 42 W
详解能耗模型
以PowerModelHostSimple
为例。
特点
这是一个线性的主机(Host
)能耗模型,该模型根据主机的平均CPU使用率来计算能耗。能耗分为两部分,待机能耗与最大能耗(staticPower
与maxPower
),
实现类
public class PowerModelHostSimple extends PowerModelHost {
private double maxPower;
private double staticPower;
public PowerModelHostSimple(final double maxPower, final double staticPower) {
if (maxPower < staticPower) {
throw new IllegalArgumentException("maxPower has to be bigger than staticPower");
}
this.maxPower = validatePower(maxPower, "maxPower");
this.staticPower = validatePower(staticPower, "staticPower");
}
@Override
public PowerMeasurement getPowerMeasurement() {
if(!getHost().isActive()){
return new PowerMeasurement();
}
final double utilizationFraction = getHost().getCpuMipsUtilization() / getHost().getTotalMipsCapacity();
return new PowerMeasurement(staticPower, (maxPower - staticPower) * utilizationFraction);
}
public double getPower(final double utilizationFraction) throws IllegalArgumentException {
if (utilizationFraction < 0 || utilizationFraction > 1) {
throw new IllegalArgumentException("utilizationFraction has to be between [0 and 1]");
}
return staticPower + (maxPower - staticPower) * utilizationFraction;
}
private static double validatePower(final double power, final String fieldName) {
if (power < 0) {
throw new IllegalArgumentException(fieldName+" cannot be negative");
}
if(power < 1){
throw new IllegalArgumentException(
fieldName + " must be in watts. A value smaller than 1 may indicate you're trying to give a percentage value instead.");
}
return power;
}
public double getMaxPower() {
return maxPower;
}
public double getStaticPower() {
return staticPower;
}
}
实现类解析
在PowerModelHostSimple
类中,主要有两个关键函数
-
getPower(final double utilizationFraction):
在一定的利用率下计算以瓦特 (W) 为单位的主机功率使用情况。public double getPower(final double utilizationFraction) throws IllegalArgumentException { if (utilizationFraction < 0 || utilizationFraction > 1) { throw new IllegalArgumentException("utilizationFraction has to be between [0 and 1]"); } return staticPower + (maxPower - staticPower) * utilizationFraction; }
所以,案例中使用主机的平均CPU利用率来计算主机(Host)的能耗。
-
getPowerMeasurement():
以PowerMeasurement
的形式返回实体的当前用电量,它可以保存其他信息,例如用电量的静态和动态部分。@Override public PowerMeasurement getPowerMeasurement() { if(!getHost().isActive()){ return new PowerMeasurement(); } final double utilizationFraction = getHost().getCpuMipsUtilization() / getHost().getTotalMipsCapacity(); return new PowerMeasurement(staticPower, (maxPower - staticPower) * utilizationFraction); }