From 67ad73c1e5f5f63233b9af915a8f23df745fd41f Mon Sep 17 00:00:00 2001 From: Zohaib Zaheer Date: Sat, 4 May 2024 20:47:50 +0200 Subject: [PATCH 01/12] Added a Resistance-Capacitance thermal model --- .../driver/telemetry/HostSystemStats.java | 2 ++ .../org/opendc/compute/simulator/SimHost.kt | 3 +- .../compute/telemetry/ComputeMetricReader.kt | 7 ++++ .../export/parquet/ParquetHostDataWriter.kt | 32 ++++++++++++------- .../telemetry/table/HostTableReader.kt | 5 +++ .../compute/SimBareMetalMachine.java | 1 - .../org/opendc/simulator/compute/SimPsu.java | 10 ++++++ .../simulator/compute/SimPsuFactories.java | 27 ++++++++++++++-- 8 files changed, 70 insertions(+), 17 deletions(-) diff --git a/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/driver/telemetry/HostSystemStats.java b/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/driver/telemetry/HostSystemStats.java index d9dba274c..031c1a8d2 100644 --- a/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/driver/telemetry/HostSystemStats.java +++ b/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/driver/telemetry/HostSystemStats.java @@ -33,6 +33,7 @@ * @param bootTime The time at which the server started. * @param powerDraw Instantaneous power draw of the system (in W). * @param energyUsage The cumulative energy usage of the system (in J). + * @param thermalPower The thermal power dissipated by the system (in W). * @param guestsTerminated The number of guests that are in a terminated state. * @param guestsRunning The number of guests that are in a running state. * @param guestsError The number of guests that are in an error state. @@ -44,6 +45,7 @@ public record HostSystemStats( Instant bootTime, double powerDraw, double energyUsage, + double thermalPower, int guestsTerminated, int guestsRunning, int guestsError, diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt index 624a612f5..fd5438cb6 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt @@ -237,6 +237,7 @@ public class SimHost( localBootTime, machine.psu.powerDraw, machine.psu.energyUsage, + machine.psu.thermalPower, terminated, running, error, @@ -261,7 +262,7 @@ public class SimHost( hypervisor.cpuCapacity, hypervisor.cpuDemand, hypervisor.cpuUsage, - hypervisor.cpuUsage / localCpuLimit, + hypervisor.cpuUsage / localCpuLimit ) } diff --git a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/ComputeMetricReader.kt b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/ComputeMetricReader.kt index 0b11b57da..31a9a3366 100644 --- a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/ComputeMetricReader.kt +++ b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/ComputeMetricReader.kt @@ -247,6 +247,7 @@ public class ComputeMetricReader( _cpuLostTime = table.cpuLostTime _powerDraw = table.powerDraw _energyUsage = table.energyUsage + _thermalPower = table.thermalPower _carbonIntensity = table.carbonIntensity _carbonEmission = table.carbonEmission _uptime = table.uptime @@ -328,6 +329,10 @@ public class ComputeMetricReader( private var _energyUsage = 0.0 private var previousPowerTotal = 0.0 + override val thermalPower: Double + get() = _thermalPower + private var _thermalPower = 0.0 + override val carbonIntensity: Double get() = _carbonIntensity private var _carbonIntensity = 0.0 @@ -378,6 +383,8 @@ public class ComputeMetricReader( _cpuLostTime = hostCpuStats.lostTime _powerDraw = hostSysStats.powerDraw _energyUsage = hostSysStats.energyUsage + _thermalPower = hostSysStats.thermalPower + _carbonIntensity = carbonTrace.getCarbonIntensity(absoluteTimestamp) _carbonIntensity = carbonTrace.getCarbonIntensity(timestampAbsolute) _carbonEmission = carbonIntensity * (energyUsage / 3600000.0) // convert energy usage from J to kWh diff --git a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/export/parquet/ParquetHostDataWriter.kt b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/export/parquet/ParquetHostDataWriter.kt index 020e67f24..08432c4c6 100644 --- a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/export/parquet/ParquetHostDataWriter.kt +++ b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/export/parquet/ParquetHostDataWriter.kt @@ -152,34 +152,39 @@ public class ParquetHostDataWriter(path: File, bufferSize: Int) : consumer.addDouble(data.energyUsage) consumer.endField("energy_usage", 19) - consumer.startField("carbon_intensity", 20) + consumer.startField("thermal_power", 20) + consumer.addDouble(data.thermalPower) + consumer.endField("thermal_power", 20) + + consumer.startField("carbon_intensity", 21) consumer.addDouble(data.carbonIntensity) - consumer.endField("carbon_intensity", 20) + consumer.endField("carbon_intensity", 21) - consumer.startField("carbon_emission", 21) + consumer.startField("carbon_emission", 22) consumer.addDouble(data.carbonEmission) - consumer.endField("carbon_emission", 21) + consumer.endField("carbon_emission", 22) - consumer.startField("uptime", 22) + consumer.startField("uptime", 23) consumer.addLong(data.uptime) - consumer.endField("uptime", 22) + consumer.endField("uptime", 23) - consumer.startField("downtime", 23) + consumer.startField("downtime", 24) consumer.addLong(data.downtime) - consumer.endField("downtime", 23) + consumer.endField("downtime", 24) val bootTime = data.bootTime if (bootTime != null) { - consumer.startField("boot_time", 24) + consumer.startField("boot_time", 25) consumer.addLong(bootTime.toEpochMilli()) - consumer.endField("boot_time", 24) + consumer.endField("boot_time", 25) + consumer.endField("boot_time", 25) } val bootTimeAbsolute = data.bootTimeAbsolute if (bootTimeAbsolute != null) { - consumer.startField("boot_time_absolute", 25) + consumer.startField("boot_time_absolute", 26) consumer.addLong(bootTimeAbsolute.toEpochMilli()) - consumer.endField("boot_time_absolute", 25) + consumer.endField("boot_time_absolute", 26) } consumer.endMessage() @@ -256,6 +261,9 @@ public class ParquetHostDataWriter(path: File, bufferSize: Int) : Types .required(PrimitiveType.PrimitiveTypeName.DOUBLE) .named("energy_usage"), + Types + .required(PrimitiveType.PrimitiveTypeName.DOUBLE) + .named("thermal_power"), Types .required(PrimitiveType.PrimitiveTypeName.DOUBLE) .named("carbon_intensity"), diff --git a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/table/HostTableReader.kt b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/table/HostTableReader.kt index d41c6dc08..b5dece45f 100644 --- a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/table/HostTableReader.kt +++ b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/table/HostTableReader.kt @@ -117,6 +117,11 @@ public interface HostTableReader { */ public val energyUsage: Double + /** + * The thermal power of the host in W (i.e., the power that is dissipated as heat). + */ + public val thermalPower: Double + /** * The current carbon intensity of the host in gCO2 / kW. */ diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimBareMetalMachine.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimBareMetalMachine.java index 11356eb28..4be6241d3 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimBareMetalMachine.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimBareMetalMachine.java @@ -61,7 +61,6 @@ public final class SimBareMetalMachine extends SimAbstractMachine { private final Memory memory; private final List net; private final List disk; - /** * Construct a {@link SimBareMetalMachine} instance. * diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java index 68dae4bfe..4ac70008f 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java @@ -45,6 +45,16 @@ public abstract class SimPsu extends SimPowerInlet { */ public abstract double getPowerDraw(); + /** + * Return the idle power of a cpu from the PSU's CPU power model + */ + public abstract double getIdlePower(); + + /** + * Return the thermal power of the machine (in W). + */ + public abstract double getThermalPower(); + /** * Return the cumulated energy usage of the machine (in J) measured at the inlet of the powers supply. */ diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java index 5b1184292..60930c119 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java @@ -82,15 +82,19 @@ public double getPowerDemand() { } @Override - public double getPowerDraw() { - return 0; - } + public double getPowerDraw() {return 0;} + + @Override + public double getIdlePower() { return 0;} @Override public double getEnergyUsage() { return 0; } + @Override + public double getThermalPower() {return 0;} + @Override InPort getCpuPower(int id, ProcessingUnit model) { final InPort port = stage.getInlet("cpu" + id); @@ -158,6 +162,23 @@ public double getPowerDraw() { return powerDraw; } + public double getIdlePower(){ + return model.computePower(0.0); + } + + @Override + public double getThermalPower() { + double dynamicPower = powerDraw; + + //TODO check with Dante with if there is a way to get idle power from scenario input + double idlePower = model.computePower(0.0); + + //TODO Figure out a better way to calculate static power + double staticPower = 20 * 0.12; // current (A) * voltage (V) based on typical values from an intel i7 + + return dynamicPower + idlePower + staticPower; + } + @Override public double getEnergyUsage() { updateEnergyUsage(clock.millis()); From 1ea1c239d9280117f7eba8b88f5c8b0180f3220d Mon Sep 17 00:00:00 2001 From: Zohaib Zaheer Date: Tue, 14 May 2024 15:21:00 +0200 Subject: [PATCH 02/12] Added temperature from power model --- .../driver/telemetry/HostSystemStats.java | 1 + .../org/opendc/compute/simulator/SimHost.kt | 3 +- .../compute/telemetry/ComputeMetricReader.kt | 8 ++++ .../export/parquet/ParquetHostDataWriter.kt | 7 ++++ .../telemetry/table/HostTableReader.kt | 5 +++ .../org/opendc/simulator/compute/SimPsu.java | 6 +++ .../simulator/compute/SimPsuFactories.java | 37 +++++++++++++------ 7 files changed, 54 insertions(+), 13 deletions(-) diff --git a/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/driver/telemetry/HostSystemStats.java b/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/driver/telemetry/HostSystemStats.java index 031c1a8d2..e454f2c9e 100644 --- a/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/driver/telemetry/HostSystemStats.java +++ b/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/driver/telemetry/HostSystemStats.java @@ -46,6 +46,7 @@ public record HostSystemStats( double powerDraw, double energyUsage, double thermalPower, + double temperatureC, int guestsTerminated, int guestsRunning, int guestsError, diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt index fd5438cb6..5f380dbf1 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt @@ -238,6 +238,7 @@ public class SimHost( machine.psu.powerDraw, machine.psu.energyUsage, machine.psu.thermalPower, + machine.psu.temperature, terminated, running, error, @@ -262,7 +263,7 @@ public class SimHost( hypervisor.cpuCapacity, hypervisor.cpuDemand, hypervisor.cpuUsage, - hypervisor.cpuUsage / localCpuLimit + hypervisor.cpuUsage / localCpuLimit, ) } diff --git a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/ComputeMetricReader.kt b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/ComputeMetricReader.kt index 31a9a3366..fcd63a3ac 100644 --- a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/ComputeMetricReader.kt +++ b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/ComputeMetricReader.kt @@ -248,6 +248,7 @@ public class ComputeMetricReader( _powerDraw = table.powerDraw _energyUsage = table.energyUsage _thermalPower = table.thermalPower + _temperature = table.temperature _carbonIntensity = table.carbonIntensity _carbonEmission = table.carbonEmission _uptime = table.uptime @@ -333,6 +334,10 @@ public class ComputeMetricReader( get() = _thermalPower private var _thermalPower = 0.0 + override val temperature: Double + get() = _temperature + private var _temperature = 0.0 + override val carbonIntensity: Double get() = _carbonIntensity private var _carbonIntensity = 0.0 @@ -384,6 +389,7 @@ public class ComputeMetricReader( _powerDraw = hostSysStats.powerDraw _energyUsage = hostSysStats.energyUsage _thermalPower = hostSysStats.thermalPower + _temperature = hostSysStats.temperatureC _carbonIntensity = carbonTrace.getCarbonIntensity(absoluteTimestamp) _carbonIntensity = carbonTrace.getCarbonIntensity(timestampAbsolute) @@ -419,6 +425,8 @@ public class ComputeMetricReader( _powerDraw = 0.0 _energyUsage = 0.0 + _thermalPower = 0.0 + _temperature = 0.0 _carbonIntensity = 0.0 _carbonEmission = 0.0 } diff --git a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/export/parquet/ParquetHostDataWriter.kt b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/export/parquet/ParquetHostDataWriter.kt index 08432c4c6..2bb0a6a4c 100644 --- a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/export/parquet/ParquetHostDataWriter.kt +++ b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/export/parquet/ParquetHostDataWriter.kt @@ -156,6 +156,10 @@ public class ParquetHostDataWriter(path: File, bufferSize: Int) : consumer.addDouble(data.thermalPower) consumer.endField("thermal_power", 20) + consumer.startField("temperature_C", 20) + consumer.addDouble(data.temperature) + consumer.endField("temperature_C", 20) + consumer.startField("carbon_intensity", 21) consumer.addDouble(data.carbonIntensity) consumer.endField("carbon_intensity", 21) @@ -264,6 +268,9 @@ public class ParquetHostDataWriter(path: File, bufferSize: Int) : Types .required(PrimitiveType.PrimitiveTypeName.DOUBLE) .named("thermal_power"), + Types + .required(PrimitiveType.PrimitiveTypeName.DOUBLE) + .named("temperature_C"), Types .required(PrimitiveType.PrimitiveTypeName.DOUBLE) .named("carbon_intensity"), diff --git a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/table/HostTableReader.kt b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/table/HostTableReader.kt index b5dece45f..551d3fc1f 100644 --- a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/table/HostTableReader.kt +++ b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/table/HostTableReader.kt @@ -122,6 +122,11 @@ public interface HostTableReader { */ public val thermalPower: Double + /** + * The current temperature of the host in degrees Celsius. + */ + public val temperature: Double + /** * The current carbon intensity of the host in gCO2 / kW. */ diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java index 4ac70008f..0891eaaf0 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java @@ -55,6 +55,12 @@ public abstract class SimPsu extends SimPowerInlet { */ public abstract double getThermalPower(); + /** + * Return the temperature of the Host in degrees Celsius based on a power equation. + */ + public abstract double getTemperature(); + + /** * Return the cumulated energy usage of the machine (in J) measured at the inlet of the powers supply. */ diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java index 60930c119..6432ddf24 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java @@ -77,24 +77,25 @@ private static final class NoopPsu extends SimPsu implements FlowStageLogic { } @Override - public double getPowerDemand() { - return 0; - } + public double getPowerDemand() { return 0;} @Override - public double getPowerDraw() {return 0;} + public double getPowerDraw() { return 0;} @Override public double getIdlePower() { return 0;} @Override - public double getEnergyUsage() { - return 0; - } + public double getEnergyUsage() { return 0;} @Override public double getThermalPower() {return 0;} + @Override + public double getTemperature() { + return 0; + } + @Override InPort getCpuPower(int id, ProcessingUnit model) { final InPort port = stage.getInlet("cpu" + id); @@ -129,6 +130,8 @@ private static final class SimplePsu extends SimPsu implements FlowStageLogic { private double powerDraw; private double energyUsage; + private double current; //FIXME implement current when PSU is fully implemented + private double voltage; //FIXME implement voltage when PSU is fully implemented private final InHandler handler = new InHandler() { @Override @@ -168,17 +171,27 @@ public double getIdlePower(){ @Override public double getThermalPower() { - double dynamicPower = powerDraw; + // defining current (A) and voltage (V) based on typical values from an intel i7 + current = 20; + voltage = 0.12; - //TODO check with Dante with if there is a way to get idle power from scenario input + double dynamicPower = powerDraw; double idlePower = model.computePower(0.0); - - //TODO Figure out a better way to calculate static power - double staticPower = 20 * 0.12; // current (A) * voltage (V) based on typical values from an intel i7 + double staticPower = current * voltage; return dynamicPower + idlePower + staticPower; } + @Override + public double getTemperature() { + // defining the temperature based on a linear equation with power draw for an Intel i7 + double yIntercept = 43.2; + double slope = 0.19; + double dynamicPower = powerDraw; + + return yIntercept + slope * dynamicPower; + } + @Override public double getEnergyUsage() { updateEnergyUsage(clock.millis()); From c002fe442050bceda992f47929d79ceafc0e6d05 Mon Sep 17 00:00:00 2001 From: Zohaib Zaheer Date: Mon, 20 May 2024 16:12:09 +0200 Subject: [PATCH 03/12] Added a test for thermal power --- .../org/opendc/simulator/compute/SimPsu.java | 5 ---- .../simulator/compute/SimPsuFactories.java | 17 ++++--------- .../opendc/simulator/compute/ThermalTest.kt | 24 +++++++++++++++++++ 3 files changed, 29 insertions(+), 17 deletions(-) create mode 100644 opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/ThermalTest.kt diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java index 0891eaaf0..7ab383937 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java @@ -45,11 +45,6 @@ public abstract class SimPsu extends SimPowerInlet { */ public abstract double getPowerDraw(); - /** - * Return the idle power of a cpu from the PSU's CPU power model - */ - public abstract double getIdlePower(); - /** * Return the thermal power of the machine (in W). */ diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java index 6432ddf24..6f25b1e2c 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java @@ -82,9 +82,6 @@ private static final class NoopPsu extends SimPsu implements FlowStageLogic { @Override public double getPowerDraw() { return 0;} - @Override - public double getIdlePower() { return 0;} - @Override public double getEnergyUsage() { return 0;} @@ -130,7 +127,7 @@ private static final class SimplePsu extends SimPsu implements FlowStageLogic { private double powerDraw; private double energyUsage; - private double current; //FIXME implement current when PSU is fully implemented + private double leakageCurrent; //FIXME implement current when PSU is fully implemented private double voltage; //FIXME implement voltage when PSU is fully implemented private final InHandler handler = new InHandler() { @@ -165,19 +162,15 @@ public double getPowerDraw() { return powerDraw; } - public double getIdlePower(){ - return model.computePower(0.0); - } - @Override public double getThermalPower() { - // defining current (A) and voltage (V) based on typical values from an intel i7 - current = 20; - voltage = 0.12; + // defining leakage current (A) and voltage (V) based on typical values from an intel i7 + leakageCurrent = 0.001; // not the same as total current for the CPU, based off the data sheet values for different input signals summed together + voltage = 1.2; double dynamicPower = powerDraw; double idlePower = model.computePower(0.0); - double staticPower = current * voltage; + double staticPower = leakageCurrent * voltage; return dynamicPower + idlePower + staticPower; } diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/ThermalTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/ThermalTest.kt new file mode 100644 index 000000000..f88ba0f1c --- /dev/null +++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/ThermalTest.kt @@ -0,0 +1,24 @@ +package org.opendc.simulator.compute + +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.Assertions.assertEquals +import org.opendc.simulator.compute.power.CpuPowerModels + +class ThermalTest { + private val maxPower = 130.0 + private val idlePower = 12.0 + private val staticPower = 0.001 * 1.2 + + private val powerModel = CpuPowerModels.linear(maxPower, idlePower) + + @Test + fun testThermalPower() { + val utilizationVals = listOf(0.25, 0.50, 0.75, 1.0) // Define the range of utilization values + val expectedThermalPower = listOf(53.5012, 83.0012, 112.5012, 142.0012) // Expected thermal power dissipation for each utilization + + utilizationVals.forEachIndexed { i, u -> + assertEquals(expectedThermalPower[i], (idlePower + staticPower + powerModel.computePower(u))) + } + + } +} From 2610e774fe2b42663a3dbe2fffd50c9610847759 Mon Sep 17 00:00:00 2001 From: Zohaib Zaheer Date: Wed, 22 May 2024 13:22:48 +0200 Subject: [PATCH 04/12] Added unit tests for thermal power and temperature. All tests pass. --- .../opendc/simulator/compute/ThermalTest.kt | 73 +++++++++++++++++-- 1 file changed, 65 insertions(+), 8 deletions(-) diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/ThermalTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/ThermalTest.kt index f88ba0f1c..7b8e21e86 100644 --- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/ThermalTest.kt +++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/ThermalTest.kt @@ -1,24 +1,81 @@ package org.opendc.simulator.compute +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.yield +import org.junit.jupiter.api.Assertions.assertAll import org.junit.jupiter.api.Test import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.BeforeEach +import org.opendc.simulator.compute.model.MachineModel +import org.opendc.simulator.compute.model.MemoryUnit +import org.opendc.simulator.compute.model.NetworkAdapter +import org.opendc.simulator.compute.model.ProcessingNode +import org.opendc.simulator.compute.model.ProcessingUnit +import org.opendc.simulator.compute.model.StorageDevice import org.opendc.simulator.compute.power.CpuPowerModels +import org.opendc.simulator.compute.workload.SimWorkloads +import org.opendc.simulator.flow2.FlowEngine +import org.opendc.simulator.power.SimPowerSource +import org.opendc.simulator.kotlin.runSimulation class ThermalTest { private val maxPower = 130.0 private val idlePower = 12.0 - private val staticPower = 0.001 * 1.2 private val powerModel = CpuPowerModels.linear(maxPower, idlePower) + private lateinit var machineModel: MachineModel - @Test - fun testThermalPower() { - val utilizationVals = listOf(0.25, 0.50, 0.75, 1.0) // Define the range of utilization values - val expectedThermalPower = listOf(53.5012, 83.0012, 112.5012, 142.0012) // Expected thermal power dissipation for each utilization + @BeforeEach + fun setUp() { + val cpuNode = ProcessingNode("Intel", "i7-900", "amd64", 8) + + machineModel = + MachineModel( + List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 3500.0) }, + List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }, + listOf(NetworkAdapter("Mellanox", "ConnectX-5", 25000.0)), + listOf(StorageDevice("Samsung", "EVO", 1000.0, 250.0, 250.0)), + ) + } + + private fun testUtilization(utilization: Double, expectedPower: Double, expectedTemperature: Double) = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val machine = + SimBareMetalMachine.create( + graph, + machineModel, + SimPsuFactories.simple(powerModel), + ) + val source = SimPowerSource(graph, 1000.0f) + source.connect(machine.psu) - utilizationVals.forEachIndexed { i, u -> - assertEquals(expectedThermalPower[i], (idlePower + staticPower + powerModel.computePower(u))) + coroutineScope { + launch { machine.runWorkload(SimWorkloads.flops(2_000, utilization)) } + + yield() + assertAll( { + assertEquals(expectedPower, machine.psu.thermalPower, 0.0001, "The power draw should be $expectedPower W") + assertEquals(expectedTemperature, machine.psu.temperature, 0.0001, "The temperature should be $expectedTemperature C") + }) + } } - } + @Test + fun zeroUtilization() = testUtilization(0.0, 24.0012, 45.48) + + @Test + fun quarterUtilization() = testUtilization(0.25, 53.5012, 51.085) + + @Test + fun halfUtilization() = testUtilization(0.50, 83.0012, 56.69) + + @Test + fun threeQuarterUtilization() = testUtilization(0.75, 112.5012, 62.295) + + @Test + fun fullUtilization() = testUtilization(1.0, 142.0012, 67.9) + } From 6bb573823c49636600802c98b633d6adf7edaa8e Mon Sep 17 00:00:00 2001 From: Zohaib Zaheer Date: Sat, 15 Jun 2024 16:19:35 +0200 Subject: [PATCH 05/12] Refactored temperature model to a Resistance-Capacitance model --- .../org/opendc/simulator/compute/SimPsu.java | 2 ++ .../simulator/compute/SimPsuFactories.java | 27 +++++++++++++------ .../opendc/simulator/compute/ThermalTest.kt | 2 +- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java index 7ab383937..57458b2bc 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java @@ -56,6 +56,8 @@ public abstract class SimPsu extends SimPowerInlet { public abstract double getTemperature(); + public abstract void setTemperature(); + /** * Return the cumulated energy usage of the machine (in J) measured at the inlet of the powers supply. */ diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java index 6f25b1e2c..966eec5b7 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java @@ -93,6 +93,10 @@ public double getTemperature() { return 0; } + @Override + public void setTemperature() { + } + @Override InPort getCpuPower(int id, ProcessingUnit model) { final InPort port = stage.getInlet("cpu" + id); @@ -127,8 +131,9 @@ private static final class SimplePsu extends SimPsu implements FlowStageLogic { private double powerDraw; private double energyUsage; - private double leakageCurrent; //FIXME implement current when PSU is fully implemented + private double leakageCurrent; //FIXME implement leakage current when PSU is fully implemented private double voltage; //FIXME implement voltage when PSU is fully implemented + private double machineTemp; private final InHandler handler = new InHandler() { @Override @@ -166,7 +171,7 @@ public double getPowerDraw() { public double getThermalPower() { // defining leakage current (A) and voltage (V) based on typical values from an intel i7 leakageCurrent = 0.001; // not the same as total current for the CPU, based off the data sheet values for different input signals summed together - voltage = 1.2; + voltage = 1.4; double dynamicPower = powerDraw; double idlePower = model.computePower(0.0); @@ -176,13 +181,17 @@ public double getThermalPower() { } @Override - public double getTemperature() { - // defining the temperature based on a linear equation with power draw for an Intel i7 - double yIntercept = 43.2; - double slope = 0.19; - double dynamicPower = powerDraw; + public void setTemperature() { + double rHS = 0.298; // thermal resistance of the heat sink + double ambientTemp = 22; // ambient temperature in degrees Celsius + double totalPowerDissipated = getThermalPower(); - return yIntercept + slope * dynamicPower; + machineTemp = ambientTemp + (totalPowerDissipated * rHS); + } + + @Override + public double getTemperature() { + return machineTemp; } @Override @@ -215,6 +224,8 @@ public long onUpdate(FlowStage ctx, long now) { out.push((float) usage); powerDraw = usage; + setTemperature(); + return Long.MAX_VALUE; } diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/ThermalTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/ThermalTest.kt index 7b8e21e86..900be83cc 100644 --- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/ThermalTest.kt +++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/ThermalTest.kt @@ -64,7 +64,7 @@ class ThermalTest { } @Test - fun zeroUtilization() = testUtilization(0.0, 24.0012, 45.48) + fun zeroUtilization() = testUtilization(0.01, 24.0012, 45.48) @Test fun quarterUtilization() = testUtilization(0.25, 53.5012, 51.085) From 53f94b883096e4ace5bbc6bc1090ec020c430097 Mon Sep 17 00:00:00 2001 From: Zohaib Zaheer Date: Sat, 15 Jun 2024 16:26:02 +0200 Subject: [PATCH 06/12] Spotless Check --- .../main/java/org/opendc/simulator/compute/SimPsu.java | 4 +++- .../org/opendc/simulator/compute/SimPsuFactories.java | 9 +++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java index 57458b2bc..5c6a5cd40 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java @@ -55,7 +55,9 @@ public abstract class SimPsu extends SimPowerInlet { */ public abstract double getTemperature(); - + /** + * Set the temperature of the Host in degrees Celsius based on a power equation. + */ public abstract void setTemperature(); /** diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java index 966eec5b7..4120f549b 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java @@ -86,16 +86,13 @@ private static final class NoopPsu extends SimPsu implements FlowStageLogic { public double getEnergyUsage() { return 0;} @Override - public double getThermalPower() {return 0;} + public double getThermalPower() { return 0;} @Override - public double getTemperature() { - return 0; - } + public double getTemperature() { return 0;} @Override - public void setTemperature() { - } + public void setTemperature() { } @Override InPort getCpuPower(int id, ProcessingUnit model) { From f24f4e3baac89cd2bf93e300af2f455c370cec00 Mon Sep 17 00:00:00 2001 From: Zohaib Zaheer Date: Mon, 17 Jun 2024 00:37:28 +0200 Subject: [PATCH 07/12] Fixed bugs with ParquetHostDataWriter --- .../compute/telemetry/ComputeMetricReader.kt | 1 - .../export/parquet/ParquetHostDataWriter.kt | 29 +++++++++---------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/ComputeMetricReader.kt b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/ComputeMetricReader.kt index fcd63a3ac..d3b0a8124 100644 --- a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/ComputeMetricReader.kt +++ b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/ComputeMetricReader.kt @@ -390,7 +390,6 @@ public class ComputeMetricReader( _energyUsage = hostSysStats.energyUsage _thermalPower = hostSysStats.thermalPower _temperature = hostSysStats.temperatureC - _carbonIntensity = carbonTrace.getCarbonIntensity(absoluteTimestamp) _carbonIntensity = carbonTrace.getCarbonIntensity(timestampAbsolute) _carbonEmission = carbonIntensity * (energyUsage / 3600000.0) // convert energy usage from J to kWh diff --git a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/export/parquet/ParquetHostDataWriter.kt b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/export/parquet/ParquetHostDataWriter.kt index 2bb0a6a4c..4f6dd43d7 100644 --- a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/export/parquet/ParquetHostDataWriter.kt +++ b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/export/parquet/ParquetHostDataWriter.kt @@ -156,39 +156,38 @@ public class ParquetHostDataWriter(path: File, bufferSize: Int) : consumer.addDouble(data.thermalPower) consumer.endField("thermal_power", 20) - consumer.startField("temperature_C", 20) + consumer.startField("temperature_C", 21) consumer.addDouble(data.temperature) - consumer.endField("temperature_C", 20) + consumer.endField("temperature_C", 21) - consumer.startField("carbon_intensity", 21) + consumer.startField("carbon_intensity", 22) consumer.addDouble(data.carbonIntensity) - consumer.endField("carbon_intensity", 21) + consumer.endField("carbon_intensity", 22) - consumer.startField("carbon_emission", 22) + consumer.startField("carbon_emission", 23) consumer.addDouble(data.carbonEmission) - consumer.endField("carbon_emission", 22) + consumer.endField("carbon_emission", 23) - consumer.startField("uptime", 23) + consumer.startField("uptime", 24) consumer.addLong(data.uptime) - consumer.endField("uptime", 23) + consumer.endField("uptime", 24) - consumer.startField("downtime", 24) + consumer.startField("downtime", 25) consumer.addLong(data.downtime) - consumer.endField("downtime", 24) + consumer.endField("downtime", 25) val bootTime = data.bootTime if (bootTime != null) { - consumer.startField("boot_time", 25) + consumer.startField("boot_time", 26) consumer.addLong(bootTime.toEpochMilli()) - consumer.endField("boot_time", 25) - consumer.endField("boot_time", 25) + consumer.endField("boot_time", 26) } val bootTimeAbsolute = data.bootTimeAbsolute if (bootTimeAbsolute != null) { - consumer.startField("boot_time_absolute", 26) + consumer.startField("boot_time_absolute", 27) consumer.addLong(bootTimeAbsolute.toEpochMilli()) - consumer.endField("boot_time_absolute", 26) + consumer.endField("boot_time_absolute", 27) } consumer.endMessage() From bee1fc8813b33581b4d4d610d43b56baa4b3db37 Mon Sep 17 00:00:00 2001 From: Zohaib Zaheer Date: Thu, 20 Jun 2024 15:00:42 +0200 Subject: [PATCH 08/12] * Added a linear interpolation model for static current * Changed how the rc model calculation is carried out --- .../org/opendc/simulator/compute/SimPsu.java | 5 ++ .../simulator/compute/SimPsuFactories.java | 54 ++++++++++++++----- 2 files changed, 46 insertions(+), 13 deletions(-) diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java index 5c6a5cd40..1ca9e91fb 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java @@ -60,6 +60,11 @@ public abstract class SimPsu extends SimPowerInlet { */ public abstract void setTemperature(); + /** + * Set the leakage current of the machine (in A). + */ + public abstract void setStaticPower(); + /** * Return the cumulated energy usage of the machine (in J) measured at the inlet of the powers supply. */ diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java index 4120f549b..1744e5b86 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java @@ -77,22 +77,35 @@ private static final class NoopPsu extends SimPsu implements FlowStageLogic { } @Override - public double getPowerDemand() { return 0;} + public double getPowerDemand() { + return 0; + } @Override - public double getPowerDraw() { return 0;} + public double getPowerDraw() { + return 0; + } @Override - public double getEnergyUsage() { return 0;} + public double getEnergyUsage() { + return 0; + } @Override - public double getThermalPower() { return 0;} + public double getThermalPower() { + return 0; + } @Override - public double getTemperature() { return 0;} + public double getTemperature() { + return 0; + } @Override - public void setTemperature() { } + public void setTemperature() {} + + @Override + public void setStaticPower() {} @Override InPort getCpuPower(int id, ProcessingUnit model) { @@ -128,8 +141,9 @@ private static final class SimplePsu extends SimPsu implements FlowStageLogic { private double powerDraw; private double energyUsage; - private double leakageCurrent; //FIXME implement leakage current when PSU is fully implemented - private double voltage; //FIXME implement voltage when PSU is fully implemented + private double voltage = 1.8; // FIXME implement voltage when PSU is fully implemented + private double current; // FIXME implement current when PSU is fully implemented + private double staticPower; private double machineTemp; private final InHandler handler = new InHandler() { @@ -165,14 +179,27 @@ public double getPowerDraw() { } @Override - public double getThermalPower() { - // defining leakage current (A) and voltage (V) based on typical values from an intel i7 - leakageCurrent = 0.001; // not the same as total current for the CPU, based off the data sheet values for different input signals summed together - voltage = 1.4; + public void setStaticPower() { + // Using linear interpolation to calculate the leakage current based on the power draw + + double maxLeakageCurrent = 0.0041; // maximum leakage current for an intel Xeon Platinum 8160 CPU + double minLeakageCurrent = 0.00035; // minimum leakage current for an intel Xeon Platinum 8160 CPU + double maxPowerDraw = model.computePower(1.0); + double minPowerDraw = model.computePower(0.0); + + double leakageCurrent = ((maxLeakageCurrent - minLeakageCurrent) + / (maxPowerDraw - minPowerDraw) + * (powerDraw - minPowerDraw)) + + minLeakageCurrent; + staticPower = leakageCurrent * voltage; + } + + @Override + public double getThermalPower() { double dynamicPower = powerDraw; double idlePower = model.computePower(0.0); - double staticPower = leakageCurrent * voltage; + double staticPower = this.staticPower; return dynamicPower + idlePower + staticPower; } @@ -222,6 +249,7 @@ public long onUpdate(FlowStage ctx, long now) { powerDraw = usage; setTemperature(); + setStaticPower(); return Long.MAX_VALUE; } From 95e9166b28d58cbf3ab256257b6337c316531887 Mon Sep 17 00:00:00 2001 From: Zohaib Zaheer Date: Fri, 12 Jul 2024 15:27:36 +0200 Subject: [PATCH 09/12] Refactored thermal model for clarity --- .../build.gradle.kts | 97 +++++++++++++++++++ .../simulator/compute/SimPsuFactories.java | 3 +- .../opendc/simulator/compute/ThermalTest.kt | 70 ++++++++----- 3 files changed, 146 insertions(+), 24 deletions(-) create mode 100644 opendc-experiments/opendc-experiments-scenario/build.gradle.kts diff --git a/opendc-experiments/opendc-experiments-scenario/build.gradle.kts b/opendc-experiments/opendc-experiments-scenario/build.gradle.kts new file mode 100644 index 000000000..302d48aa4 --- /dev/null +++ b/opendc-experiments/opendc-experiments-scenario/build.gradle.kts @@ -0,0 +1,97 @@ + +/* + * Copyright (c) 2019 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +description = "Experiments for the Scenario work" + +// Build configuration +plugins { + `kotlin-library-conventions` + `kotlin-conventions` + `testing-conventions` + `jacoco-conventions` + `benchmark-conventions` + distribution + kotlin("plugin.serialization") version "1.9.22" +} + +dependencies { + implementation(projects.opendcSimulator.opendcSimulatorCore) + implementation(projects.opendcSimulator.opendcSimulatorCompute) + implementation(projects.opendcCompute.opendcComputeSimulator) + + implementation(libs.clikt) + implementation(libs.progressbar) + implementation(libs.kotlin.logging) + + implementation(libs.jackson.module.kotlin) + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0") + + implementation(project(mapOf("path" to ":opendc-compute:opendc-compute-telemetry"))) + implementation(project(mapOf("path" to ":opendc-compute:opendc-compute-topology"))) + implementation(project(mapOf("path" to ":opendc-compute:opendc-compute-workload"))) + implementation(project(mapOf("path" to ":opendc-experiments:opendc-experiments-base"))) + + runtimeOnly(libs.log4j.core) + runtimeOnly(libs.log4j.slf4j) +} + +val createScenarioApp by tasks.creating(CreateStartScripts::class) { + dependsOn(tasks.jar) + + applicationName = "scenario" + mainClass.set("org.opendc.experiments.scenario.ScenarioCLI") + classpath = tasks.jar.get().outputs.files + configurations["runtimeClasspath"] + outputDir = project.buildDir.resolve("scripts") +} + +// Create custom Greenifier distribution +distributions { + main { + distributionBaseName.set("scenario") + + contents { + from("README.md") + from("LICENSE.txt") + from("../../LICENSE.txt") { + rename { "LICENSE-OpenDC.txt" } + } + + into("bin") { + from(createScenarioApp) + } + + into("lib") { + from(tasks.jar) + from(configurations["runtimeClasspath"]) + } + + into("resources") { + from("src/main/resources") + } + + into("Python_scripts") { + from("src/main/Python_scripts") + } + } + } +} diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java index 1744e5b86..a0591bf27 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java @@ -207,10 +207,11 @@ public double getThermalPower() { @Override public void setTemperature() { double rHS = 0.298; // thermal resistance of the heat sink + double rCase = 0.00061; // thermal resistance of the case double ambientTemp = 22; // ambient temperature in degrees Celsius double totalPowerDissipated = getThermalPower(); - machineTemp = ambientTemp + (totalPowerDissipated * rHS); + machineTemp = ambientTemp + (totalPowerDissipated * (rHS + rCase)); } @Override diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/ThermalTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/ThermalTest.kt index 900be83cc..d1ccc2c49 100644 --- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/ThermalTest.kt +++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/ThermalTest.kt @@ -1,12 +1,34 @@ +/* + * Copyright (c) 2024 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + package org.opendc.simulator.compute import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.launch import kotlinx.coroutines.yield import org.junit.jupiter.api.Assertions.assertAll -import org.junit.jupiter.api.Test import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test import org.opendc.simulator.compute.model.MachineModel import org.opendc.simulator.compute.model.MemoryUnit import org.opendc.simulator.compute.model.NetworkAdapter @@ -16,8 +38,8 @@ import org.opendc.simulator.compute.model.StorageDevice import org.opendc.simulator.compute.power.CpuPowerModels import org.opendc.simulator.compute.workload.SimWorkloads import org.opendc.simulator.flow2.FlowEngine -import org.opendc.simulator.power.SimPowerSource import org.opendc.simulator.kotlin.runSimulation +import org.opendc.simulator.power.SimPowerSource class ThermalTest { private val maxPower = 130.0 @@ -39,29 +61,32 @@ class ThermalTest { ) } - private fun testUtilization(utilization: Double, expectedPower: Double, expectedTemperature: Double) = - runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val machine = - SimBareMetalMachine.create( - graph, - machineModel, - SimPsuFactories.simple(powerModel), - ) - val source = SimPowerSource(graph, 1000.0f) - source.connect(machine.psu) + private fun testUtilization( + utilization: Double, + expectedPower: Double, + expectedTemperature: Double, + ) = runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val machine = + SimBareMetalMachine.create( + graph, + machineModel, + SimPsuFactories.simple(powerModel), + ) + val source = SimPowerSource(graph, 1000.0f) + source.connect(machine.psu) - coroutineScope { - launch { machine.runWorkload(SimWorkloads.flops(2_000, utilization)) } + coroutineScope { + launch { machine.runWorkload(SimWorkloads.flops(2_000, utilization)) } - yield() - assertAll( { - assertEquals(expectedPower, machine.psu.thermalPower, 0.0001, "The power draw should be $expectedPower W") - assertEquals(expectedTemperature, machine.psu.temperature, 0.0001, "The temperature should be $expectedTemperature C") - }) - } + yield() + assertAll({ + assertEquals(expectedPower, machine.psu.thermalPower, 0.0001, "The power draw should be $expectedPower W") + assertEquals(expectedTemperature, machine.psu.temperature, 0.0001, "The temperature should be $expectedTemperature C") + }) } + } @Test fun zeroUtilization() = testUtilization(0.01, 24.0012, 45.48) @@ -77,5 +102,4 @@ class ThermalTest { @Test fun fullUtilization() = testUtilization(1.0, 142.0012, 67.9) - } From a3ac6f428c91d7853683c18e7dd9e6989af05244 Mon Sep 17 00:00:00 2001 From: Zohaib Zaheer Date: Thu, 25 Jul 2024 19:22:01 +0200 Subject: [PATCH 10/12] * Created a new class for the thermal models * Refactored code to include the new class * Exposed the parameters of the thermal model to the JSON topology front end. --- .../driver/telemetry/HostSystemStats.java | 2 - .../org/opendc/compute/simulator/SimHost.kt | 1 - .../compute/telemetry/ComputeMetricReader.kt | 7 -- .../export/parquet/ParquetHostDataWriter.kt | 35 ++++----- .../telemetry/table/HostTableReader.kt | 5 -- .../compute/topology/TopologyFactories.kt | 12 ++- .../compute/topology/specs/TopologySpecs.kt | 19 +++++ .../build.gradle.kts | 2 +- .../org/opendc/simulator/compute/SimPsu.java | 10 --- .../simulator/compute/SimPsuFactories.java | 52 +++---------- .../compute/thermal/ThermalModel.java | 28 +++++++ .../compute/thermal/ThermalModelFactories.kt | 60 +++++++++++++++ .../compute/thermal/ThermalModels.java | 76 +++++++++++++++++++ .../org/opendc/web/runner/OpenDCRunner.kt | 4 +- 14 files changed, 221 insertions(+), 92 deletions(-) create mode 100644 opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModel.java create mode 100644 opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModelFactories.kt create mode 100644 opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModels.java diff --git a/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/driver/telemetry/HostSystemStats.java b/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/driver/telemetry/HostSystemStats.java index e454f2c9e..4b7a1ac3d 100644 --- a/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/driver/telemetry/HostSystemStats.java +++ b/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/driver/telemetry/HostSystemStats.java @@ -33,7 +33,6 @@ * @param bootTime The time at which the server started. * @param powerDraw Instantaneous power draw of the system (in W). * @param energyUsage The cumulative energy usage of the system (in J). - * @param thermalPower The thermal power dissipated by the system (in W). * @param guestsTerminated The number of guests that are in a terminated state. * @param guestsRunning The number of guests that are in a running state. * @param guestsError The number of guests that are in an error state. @@ -45,7 +44,6 @@ public record HostSystemStats( Instant bootTime, double powerDraw, double energyUsage, - double thermalPower, double temperatureC, int guestsTerminated, int guestsRunning, diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt index 5f380dbf1..e0b06f272 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt @@ -237,7 +237,6 @@ public class SimHost( localBootTime, machine.psu.powerDraw, machine.psu.energyUsage, - machine.psu.thermalPower, machine.psu.temperature, terminated, running, diff --git a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/ComputeMetricReader.kt b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/ComputeMetricReader.kt index d3b0a8124..51d7ed740 100644 --- a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/ComputeMetricReader.kt +++ b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/ComputeMetricReader.kt @@ -247,7 +247,6 @@ public class ComputeMetricReader( _cpuLostTime = table.cpuLostTime _powerDraw = table.powerDraw _energyUsage = table.energyUsage - _thermalPower = table.thermalPower _temperature = table.temperature _carbonIntensity = table.carbonIntensity _carbonEmission = table.carbonEmission @@ -330,10 +329,6 @@ public class ComputeMetricReader( private var _energyUsage = 0.0 private var previousPowerTotal = 0.0 - override val thermalPower: Double - get() = _thermalPower - private var _thermalPower = 0.0 - override val temperature: Double get() = _temperature private var _temperature = 0.0 @@ -388,7 +383,6 @@ public class ComputeMetricReader( _cpuLostTime = hostCpuStats.lostTime _powerDraw = hostSysStats.powerDraw _energyUsage = hostSysStats.energyUsage - _thermalPower = hostSysStats.thermalPower _temperature = hostSysStats.temperatureC _carbonIntensity = carbonTrace.getCarbonIntensity(timestampAbsolute) @@ -424,7 +418,6 @@ public class ComputeMetricReader( _powerDraw = 0.0 _energyUsage = 0.0 - _thermalPower = 0.0 _temperature = 0.0 _carbonIntensity = 0.0 _carbonEmission = 0.0 diff --git a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/export/parquet/ParquetHostDataWriter.kt b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/export/parquet/ParquetHostDataWriter.kt index 4f6dd43d7..9cd8e6a5c 100644 --- a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/export/parquet/ParquetHostDataWriter.kt +++ b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/export/parquet/ParquetHostDataWriter.kt @@ -152,42 +152,38 @@ public class ParquetHostDataWriter(path: File, bufferSize: Int) : consumer.addDouble(data.energyUsage) consumer.endField("energy_usage", 19) - consumer.startField("thermal_power", 20) - consumer.addDouble(data.thermalPower) - consumer.endField("thermal_power", 20) - - consumer.startField("temperature_C", 21) + consumer.startField("temperature_C", 20) consumer.addDouble(data.temperature) - consumer.endField("temperature_C", 21) + consumer.endField("temperature_C", 20) - consumer.startField("carbon_intensity", 22) + consumer.startField("carbon_intensity", 21) consumer.addDouble(data.carbonIntensity) - consumer.endField("carbon_intensity", 22) + consumer.endField("carbon_intensity", 21) - consumer.startField("carbon_emission", 23) + consumer.startField("carbon_emission", 22) consumer.addDouble(data.carbonEmission) - consumer.endField("carbon_emission", 23) + consumer.endField("carbon_emission", 22) - consumer.startField("uptime", 24) + consumer.startField("uptime", 23) consumer.addLong(data.uptime) - consumer.endField("uptime", 24) + consumer.endField("uptime", 23) - consumer.startField("downtime", 25) + consumer.startField("downtime", 24) consumer.addLong(data.downtime) - consumer.endField("downtime", 25) + consumer.endField("downtime", 24) val bootTime = data.bootTime if (bootTime != null) { - consumer.startField("boot_time", 26) + consumer.startField("boot_time", 25) consumer.addLong(bootTime.toEpochMilli()) - consumer.endField("boot_time", 26) + consumer.endField("boot_time", 25) } val bootTimeAbsolute = data.bootTimeAbsolute if (bootTimeAbsolute != null) { - consumer.startField("boot_time_absolute", 27) + consumer.startField("boot_time_absolute", 26) consumer.addLong(bootTimeAbsolute.toEpochMilli()) - consumer.endField("boot_time_absolute", 27) + consumer.endField("boot_time_absolute", 26) } consumer.endMessage() @@ -264,9 +260,6 @@ public class ParquetHostDataWriter(path: File, bufferSize: Int) : Types .required(PrimitiveType.PrimitiveTypeName.DOUBLE) .named("energy_usage"), - Types - .required(PrimitiveType.PrimitiveTypeName.DOUBLE) - .named("thermal_power"), Types .required(PrimitiveType.PrimitiveTypeName.DOUBLE) .named("temperature_C"), diff --git a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/table/HostTableReader.kt b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/table/HostTableReader.kt index 551d3fc1f..604da3210 100644 --- a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/table/HostTableReader.kt +++ b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/table/HostTableReader.kt @@ -117,11 +117,6 @@ public interface HostTableReader { */ public val energyUsage: Double - /** - * The thermal power of the host in W (i.e., the power that is dissipated as heat). - */ - public val thermalPower: Double - /** * The current temperature of the host in degrees Celsius. */ diff --git a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyFactories.kt b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyFactories.kt index 656085e84..e9d5d1435 100644 --- a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyFactories.kt +++ b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyFactories.kt @@ -34,6 +34,7 @@ import org.opendc.simulator.compute.model.MemoryUnit import org.opendc.simulator.compute.model.ProcessingNode import org.opendc.simulator.compute.model.ProcessingUnit import org.opendc.simulator.compute.power.getPowerModel +import org.opendc.simulator.compute.thermal.getThermalModel import java.io.File import java.io.InputStream import java.util.SplittableRandom @@ -130,6 +131,15 @@ private fun HostJSONSpec.toHostSpecs( ) val powerModel = getPowerModel(powerModel.modelType, powerModel.power, powerModel.maxPower, powerModel.idlePower) + val thermalModel = + getThermalModel( + thermalModel.modelType, + thermalModel.rHS, + thermalModel.rCase, + thermalModel.ambientTemperature, + thermalModel.minLeakageCurrent, + thermalModel.maxLeakageCurrent, + ) var hostName: String if (name == null) { @@ -144,7 +154,7 @@ private fun HostJSONSpec.toHostSpecs( hostName, mapOf("cluster" to clusterId), machineModel, - SimPsuFactories.simple(powerModel), + SimPsuFactories.simple(powerModel, thermalModel), ) hostId++ diff --git a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/TopologySpecs.kt b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/TopologySpecs.kt index 110d6fb15..c8d9f2a29 100644 --- a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/TopologySpecs.kt +++ b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/TopologySpecs.kt @@ -65,6 +65,15 @@ public data class HostJSONSpec( val cpu: CPUSpec, val memory: MemorySpec, val powerModel: PowerModelSpec = PowerModelSpec("linear", 350.0, 400.0, 200.0), + val thermalModel: ThermalModelSpec = + ThermalModelSpec( + "rcmodel", + 0.298, + 0.00061, + 0.00035, + 0.0041, + 22.0, + ), val count: Int = 1, ) @@ -116,3 +125,13 @@ public data class PowerModelSpec( require(maxPower >= idlePower) { "The max power of a power model can not be less than the idle power" } } } + +@Serializable +public data class ThermalModelSpec( + val modelType: String, + val rHS: Double, + val rCase: Double, + val minLeakageCurrent: Double, + val maxLeakageCurrent: Double, + val ambientTemperature: Double, +) diff --git a/opendc-experiments/opendc-experiments-scenario/build.gradle.kts b/opendc-experiments/opendc-experiments-scenario/build.gradle.kts index 302d48aa4..f9d0add6e 100644 --- a/opendc-experiments/opendc-experiments-scenario/build.gradle.kts +++ b/opendc-experiments/opendc-experiments-scenario/build.gradle.kts @@ -59,7 +59,7 @@ val createScenarioApp by tasks.creating(CreateStartScripts::class) { dependsOn(tasks.jar) applicationName = "scenario" - mainClass.set("org.opendc.experiments.scenario.ScenarioCLI") + mainClass.set("org.opendc.experiments.scenario.ScenarioCli") classpath = tasks.jar.get().outputs.files + configurations["runtimeClasspath"] outputDir = project.buildDir.resolve("scripts") } diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java index 1ca9e91fb..cb22234dc 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java @@ -45,11 +45,6 @@ public abstract class SimPsu extends SimPowerInlet { */ public abstract double getPowerDraw(); - /** - * Return the thermal power of the machine (in W). - */ - public abstract double getThermalPower(); - /** * Return the temperature of the Host in degrees Celsius based on a power equation. */ @@ -60,11 +55,6 @@ public abstract class SimPsu extends SimPowerInlet { */ public abstract void setTemperature(); - /** - * Set the leakage current of the machine (in A). - */ - public abstract void setStaticPower(); - /** * Return the cumulated energy usage of the machine (in J) measured at the inlet of the powers supply. */ diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java index a0591bf27..53ac35ba7 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java @@ -26,6 +26,7 @@ import org.jetbrains.annotations.NotNull; import org.opendc.simulator.compute.model.ProcessingUnit; import org.opendc.simulator.compute.power.CpuPowerModel; +import org.opendc.simulator.compute.thermal.ThermalModel; import org.opendc.simulator.flow2.FlowGraph; import org.opendc.simulator.flow2.FlowStage; import org.opendc.simulator.flow2.FlowStageLogic; @@ -57,8 +58,8 @@ public static SimPsuFactory noop() { * * @param model The power model to estimate the power consumption based on the CPU usage. */ - public static SimPsuFactory simple(CpuPowerModel model) { - return (machine, graph) -> new SimplePsu(graph, model); + public static SimPsuFactory simple(CpuPowerModel model, ThermalModel thermalModel) { + return (machine, graph) -> new SimplePsu(graph, model, thermalModel); } /** @@ -91,11 +92,6 @@ public double getEnergyUsage() { return 0; } - @Override - public double getThermalPower() { - return 0; - } - @Override public double getTemperature() { return 0; @@ -104,9 +100,6 @@ public double getTemperature() { @Override public void setTemperature() {} - @Override - public void setStaticPower() {} - @Override InPort getCpuPower(int id, ProcessingUnit model) { final InPort port = stage.getInlet("cpu" + id); @@ -133,6 +126,7 @@ private static final class SimplePsu extends SimPsu implements FlowStageLogic { private final FlowStage stage; private final OutPort out; private final CpuPowerModel model; + private final ThermalModel thermalModel; private final InstantSource clock; private double targetFreq; @@ -158,10 +152,11 @@ public void onUpstreamFinish(InPort port, Throwable cause) { } }; - SimplePsu(FlowGraph graph, CpuPowerModel model) { + SimplePsu(FlowGraph graph, CpuPowerModel model, ThermalModel thermalModel) { this.stage = graph.newStage(this); this.model = model; this.clock = graph.getEngine().getClock(); + this.thermalModel = thermalModel; this.out = stage.getOutlet("out"); this.out.setMask(true); @@ -178,40 +173,12 @@ public double getPowerDraw() { return powerDraw; } - @Override - public void setStaticPower() { - // Using linear interpolation to calculate the leakage current based on the power draw - - double maxLeakageCurrent = 0.0041; // maximum leakage current for an intel Xeon Platinum 8160 CPU - double minLeakageCurrent = 0.00035; // minimum leakage current for an intel Xeon Platinum 8160 CPU - double maxPowerDraw = model.computePower(1.0); - double minPowerDraw = model.computePower(0.0); - - double leakageCurrent = ((maxLeakageCurrent - minLeakageCurrent) - / (maxPowerDraw - minPowerDraw) - * (powerDraw - minPowerDraw)) - + minLeakageCurrent; - - staticPower = leakageCurrent * voltage; - } - - @Override - public double getThermalPower() { - double dynamicPower = powerDraw; - double idlePower = model.computePower(0.0); - double staticPower = this.staticPower; - - return dynamicPower + idlePower + staticPower; - } - @Override public void setTemperature() { - double rHS = 0.298; // thermal resistance of the heat sink - double rCase = 0.00061; // thermal resistance of the case - double ambientTemp = 22; // ambient temperature in degrees Celsius - double totalPowerDissipated = getThermalPower(); + double minPower = model.computePower(0.0); + double maxPower = model.computePower(1.0); - machineTemp = ambientTemp + (totalPowerDissipated * (rHS + rCase)); + machineTemp = thermalModel.setTemperature(powerDraw, minPower, maxPower); } @Override @@ -250,7 +217,6 @@ public long onUpdate(FlowStage ctx, long now) { powerDraw = usage; setTemperature(); - setStaticPower(); return Long.MAX_VALUE; } diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModel.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModel.java new file mode 100644 index 000000000..b45242450 --- /dev/null +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModel.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.opendc.simulator.compute.thermal; + +public interface ThermalModel { + + double setTemperature(double dynamicPower, double minPower, double maxPower); +} diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModelFactories.kt b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModelFactories.kt new file mode 100644 index 000000000..85ba5b979 --- /dev/null +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModelFactories.kt @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2024 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.opendc.simulator.compute.thermal + +public fun getThermalModel( + modelType: String, + rHS: Double, + rCase: Double, + minLeakageCurrent: Double, + maxLeakageCurrent: Double, + ambientTemperature: Double, +): ThermalModel { + return when (modelType) { + "rcmodel" -> + ThermalModels.rcmodel( + rHS, + rCase, + minLeakageCurrent, + maxLeakageCurrent, + ambientTemperature, + ) + + else -> throw IllegalArgumentException("Unknown power modelType $modelType") + } +} + +public fun getThermalModel(modelType: String): ThermalModel { + return when (modelType) { + "rcmodel" -> + ThermalModels.rcmodel( + 0.298, + 0.00061, + 0.00035, + 0.0041, + 22.0, + ) + + else -> throw IllegalArgumentException("Unknown power modelType $modelType") + } +} diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModels.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModels.java new file mode 100644 index 000000000..2eaf468ae --- /dev/null +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModels.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2024 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.opendc.simulator.compute.thermal; + +public class ThermalModels { + + public static ThermalModel rcmodel( + double rHS, double rCase, double minLeakageCurrent, double maxLeakageCurrent, double ambientTemperature) { + return new RCModel(rHS, rCase, minLeakageCurrent, maxLeakageCurrent, ambientTemperature); + } + + private static class RCModel implements ThermalModel { + protected final double rHS; + protected final double rCase; + protected final double minLeakageCurrent; + protected final double maxLeakageCurrent; + protected final double ambientTemperature; + + private RCModel( + double rHS, + double rCase, + double minLeakageCurrent, + double maxLeakageCurrent, + double ambientTemperature) { + this.rHS = rHS; + this.rCase = rCase; + this.minLeakageCurrent = minLeakageCurrent; + this.maxLeakageCurrent = maxLeakageCurrent; + this.ambientTemperature = ambientTemperature; + } + + private double setThermalPower(double dynamicPower, double minPower, double maxPower) { + double staticPower = + ((maxLeakageCurrent - minLeakageCurrent) / (maxPower - minPower) * (dynamicPower - minPower)) + + minLeakageCurrent; + + return dynamicPower + minPower + staticPower; + } + + @Override + public double setTemperature(double dynamicPower, double minPower, double maxPower) { + double totalPowerDissipated = setThermalPower(dynamicPower, minPower, maxPower); + + return ambientTemperature + (totalPowerDissipated * (rHS + rCase)); + } + } + + // TODO Implement this model + private static class ManufacturerModel implements ThermalModel { + + @Override + public double setTemperature(double dynamicPower, double minPower, double maxPower) { + return 0; + } + } +} diff --git a/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt b/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt index 7eb6e21fe..d8257a5a2 100644 --- a/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt +++ b/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt @@ -42,6 +42,7 @@ import org.opendc.simulator.compute.model.MemoryUnit import org.opendc.simulator.compute.model.ProcessingNode import org.opendc.simulator.compute.model.ProcessingUnit import org.opendc.simulator.compute.power.CpuPowerModels +import org.opendc.simulator.compute.thermal.ThermalModels import org.opendc.simulator.kotlin.runSimulation import org.opendc.web.proto.runner.Job import org.opendc.web.proto.runner.Scenario @@ -346,6 +347,7 @@ public class OpenDCRunner( val energyConsumptionW = machine.cpus.sumOf { it.energyConsumptionW } val powerModel = CpuPowerModels.linear(2 * energyConsumptionW, energyConsumptionW * 0.5) + val thermalModel = ThermalModels.rcmodel(0.298, 0.00061, 0.00035, 0.0041, 22.0) val spec = HostSpec( @@ -353,7 +355,7 @@ public class OpenDCRunner( "node-$clusterId-$position", mapOf("cluster" to clusterId), MachineModel(processors, memoryUnits), - SimPsuFactories.simple(powerModel), + SimPsuFactories.simple(powerModel, thermalModel), ) res += spec From a2c3c3f59cf79428881a58da0f5aedde406b0949 Mon Sep 17 00:00:00 2001 From: Zohaib Zaheer Date: Sat, 27 Jul 2024 19:14:58 +0400 Subject: [PATCH 11/12] * Bug Fix: static power now properly takes into account voltage * Added code for manufacturer approach --- .../compute/topology/TopologyFactories.kt | 3 +- .../compute/topology/specs/TopologySpecs.kt | 2 + .../compute/thermal/ThermalModelFactories.kt | 5 +++ .../compute/thermal/ThermalModels.java | 41 ++++++++++++++----- 4 files changed, 39 insertions(+), 12 deletions(-) diff --git a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyFactories.kt b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyFactories.kt index e9d5d1435..ee1be5aa7 100644 --- a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyFactories.kt +++ b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyFactories.kt @@ -136,9 +136,10 @@ private fun HostJSONSpec.toHostSpecs( thermalModel.modelType, thermalModel.rHS, thermalModel.rCase, - thermalModel.ambientTemperature, thermalModel.minLeakageCurrent, thermalModel.maxLeakageCurrent, + thermalModel.supplyVoltage, + thermalModel.ambientTemperature, ) var hostName: String diff --git a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/TopologySpecs.kt b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/TopologySpecs.kt index c8d9f2a29..bab394823 100644 --- a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/TopologySpecs.kt +++ b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/TopologySpecs.kt @@ -72,6 +72,7 @@ public data class HostJSONSpec( 0.00061, 0.00035, 0.0041, + 1.8, 22.0, ), val count: Int = 1, @@ -133,5 +134,6 @@ public data class ThermalModelSpec( val rCase: Double, val minLeakageCurrent: Double, val maxLeakageCurrent: Double, + val supplyVoltage: Double, val ambientTemperature: Double, ) diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModelFactories.kt b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModelFactories.kt index 85ba5b979..188368d8d 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModelFactories.kt +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModelFactories.kt @@ -28,6 +28,7 @@ public fun getThermalModel( rCase: Double, minLeakageCurrent: Double, maxLeakageCurrent: Double, + supplyVoltage: Double, ambientTemperature: Double, ): ThermalModel { return when (modelType) { @@ -37,6 +38,7 @@ public fun getThermalModel( rCase, minLeakageCurrent, maxLeakageCurrent, + supplyVoltage, ambientTemperature, ) @@ -52,8 +54,11 @@ public fun getThermalModel(modelType: String): ThermalModel { 0.00061, 0.00035, 0.0041, + 1.8, 22.0, ) + "manufacturerModel" -> + ThermalModels.manufacturerModel(0.278, 47.0) else -> throw IllegalArgumentException("Unknown power modelType $modelType") } diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModels.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModels.java index 2eaf468ae..f631553a0 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModels.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModels.java @@ -25,8 +25,12 @@ public class ThermalModels { public static ThermalModel rcmodel( - double rHS, double rCase, double minLeakageCurrent, double maxLeakageCurrent, double ambientTemperature) { - return new RCModel(rHS, rCase, minLeakageCurrent, maxLeakageCurrent, ambientTemperature); + double rHS, double rCase, double minLeakageCurrent, double maxLeakageCurrent, double supplyVoltage, double ambientTemperature) { + return new RCModel(rHS, rCase, minLeakageCurrent, maxLeakageCurrent, supplyVoltage, ambientTemperature); + } + + public static ThermalModel manufacturerModel(double slope, double intercept) { + return new ManufacturerModel(slope, intercept); } private static class RCModel implements ThermalModel { @@ -35,42 +39,57 @@ private static class RCModel implements ThermalModel { protected final double minLeakageCurrent; protected final double maxLeakageCurrent; protected final double ambientTemperature; + protected final double supplyVoltage; + + private double currentStaticPower; + private double totalPowerDissipated; private RCModel( double rHS, double rCase, double minLeakageCurrent, double maxLeakageCurrent, + double supplyVoltage, double ambientTemperature) { this.rHS = rHS; this.rCase = rCase; this.minLeakageCurrent = minLeakageCurrent; this.maxLeakageCurrent = maxLeakageCurrent; + this.supplyVoltage = supplyVoltage; this.ambientTemperature = ambientTemperature; } - private double setThermalPower(double dynamicPower, double minPower, double maxPower) { - double staticPower = - ((maxLeakageCurrent - minLeakageCurrent) / (maxPower - minPower) * (dynamicPower - minPower)) - + minLeakageCurrent; + private void setStaticPower(double dynamicPower, double minPower, double maxPower) { + currentStaticPower = + ((maxLeakageCurrent - minLeakageCurrent) / (maxPower - minPower) * (dynamicPower - minPower)) + + minLeakageCurrent; + } - return dynamicPower + minPower + staticPower; + private void setThermalPower(double dynamicPower, double minPower) { + totalPowerDissipated = dynamicPower + minPower + currentStaticPower; } @Override public double setTemperature(double dynamicPower, double minPower, double maxPower) { - double totalPowerDissipated = setThermalPower(dynamicPower, minPower, maxPower); + setStaticPower(dynamicPower, minPower, maxPower); + setThermalPower(dynamicPower, minPower); - return ambientTemperature + (totalPowerDissipated * (rHS + rCase)); + return ambientTemperature + (totalPowerDissipated * (rHS + rCase)); } } - // TODO Implement this model private static class ManufacturerModel implements ThermalModel { + protected final double slope; + protected final double intercept; + + private ManufacturerModel(double slope, double intercept) { + this.slope = slope; + this.intercept = intercept; + } @Override public double setTemperature(double dynamicPower, double minPower, double maxPower) { - return 0; + return slope * dynamicPower + intercept; } } } From a46ea88b841bcf19e8dbd14d47b5e69af086b682 Mon Sep 17 00:00:00 2001 From: Zohaib Zaheer Date: Sun, 11 Aug 2024 01:21:54 +0400 Subject: [PATCH 12/12] Made changes based on feedback from PR --- .../driver/telemetry/HostSystemStats.java | 2 +- .../org/opendc/compute/simulator/SimHost.kt | 2 +- .../compute/telemetry/ComputeMetricReader.kt | 12 +-- .../export/parquet/ParquetHostDataWriter.kt | 8 +- .../telemetry/table/HostTableReader.kt | 2 +- .../compute/topology/specs/TopologySpecs.kt | 1 + .../build.gradle.kts | 97 ------------------- .../org/opendc/simulator/compute/SimPsu.java | 2 +- .../simulator/compute/SimPsuFactories.java | 4 +- .../compute/thermal/ThermalModelFactories.kt | 22 ++++- .../compute/thermal/ThermalModels.java | 13 ++- .../opendc/simulator/compute/ThermalTest.kt | 2 +- .../org/opendc/web/runner/OpenDCRunner.kt | 10 +- 13 files changed, 54 insertions(+), 123 deletions(-) delete mode 100644 opendc-experiments/opendc-experiments-scenario/build.gradle.kts diff --git a/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/driver/telemetry/HostSystemStats.java b/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/driver/telemetry/HostSystemStats.java index 4b7a1ac3d..68b22d754 100644 --- a/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/driver/telemetry/HostSystemStats.java +++ b/opendc-compute/opendc-compute-service/src/main/java/org/opendc/compute/service/driver/telemetry/HostSystemStats.java @@ -44,7 +44,7 @@ public record HostSystemStats( Instant bootTime, double powerDraw, double energyUsage, - double temperatureC, + double cpuTemperature, int guestsTerminated, int guestsRunning, int guestsError, diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt index e0b06f272..3f9f429bc 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt +++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/SimHost.kt @@ -237,7 +237,7 @@ public class SimHost( localBootTime, machine.psu.powerDraw, machine.psu.energyUsage, - machine.psu.temperature, + machine.psu.cpuTemperature, terminated, running, error, diff --git a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/ComputeMetricReader.kt b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/ComputeMetricReader.kt index 51d7ed740..698c0cb02 100644 --- a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/ComputeMetricReader.kt +++ b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/ComputeMetricReader.kt @@ -247,7 +247,7 @@ public class ComputeMetricReader( _cpuLostTime = table.cpuLostTime _powerDraw = table.powerDraw _energyUsage = table.energyUsage - _temperature = table.temperature + _cpuTemperature = table.cpuTemperature _carbonIntensity = table.carbonIntensity _carbonEmission = table.carbonEmission _uptime = table.uptime @@ -329,9 +329,9 @@ public class ComputeMetricReader( private var _energyUsage = 0.0 private var previousPowerTotal = 0.0 - override val temperature: Double - get() = _temperature - private var _temperature = 0.0 + override val cpuTemperature: Double + get() = _cpuTemperature + private var _cpuTemperature = 0.0 override val carbonIntensity: Double get() = _carbonIntensity @@ -383,7 +383,7 @@ public class ComputeMetricReader( _cpuLostTime = hostCpuStats.lostTime _powerDraw = hostSysStats.powerDraw _energyUsage = hostSysStats.energyUsage - _temperature = hostSysStats.temperatureC + _cpuTemperature = hostSysStats.cpuTemperature _carbonIntensity = carbonTrace.getCarbonIntensity(timestampAbsolute) _carbonEmission = carbonIntensity * (energyUsage / 3600000.0) // convert energy usage from J to kWh @@ -418,7 +418,7 @@ public class ComputeMetricReader( _powerDraw = 0.0 _energyUsage = 0.0 - _temperature = 0.0 + _cpuTemperature = 0.0 _carbonIntensity = 0.0 _carbonEmission = 0.0 } diff --git a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/export/parquet/ParquetHostDataWriter.kt b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/export/parquet/ParquetHostDataWriter.kt index 9cd8e6a5c..ff8a63feb 100644 --- a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/export/parquet/ParquetHostDataWriter.kt +++ b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/export/parquet/ParquetHostDataWriter.kt @@ -152,9 +152,9 @@ public class ParquetHostDataWriter(path: File, bufferSize: Int) : consumer.addDouble(data.energyUsage) consumer.endField("energy_usage", 19) - consumer.startField("temperature_C", 20) - consumer.addDouble(data.temperature) - consumer.endField("temperature_C", 20) + consumer.startField("cpuTemperature", 20) + consumer.addDouble(data.cpuTemperature) + consumer.endField("cpuTemperature", 20) consumer.startField("carbon_intensity", 21) consumer.addDouble(data.carbonIntensity) @@ -262,7 +262,7 @@ public class ParquetHostDataWriter(path: File, bufferSize: Int) : .named("energy_usage"), Types .required(PrimitiveType.PrimitiveTypeName.DOUBLE) - .named("temperature_C"), + .named("cpuTemperature"), Types .required(PrimitiveType.PrimitiveTypeName.DOUBLE) .named("carbon_intensity"), diff --git a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/table/HostTableReader.kt b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/table/HostTableReader.kt index 604da3210..b1971219d 100644 --- a/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/table/HostTableReader.kt +++ b/opendc-compute/opendc-compute-telemetry/src/main/kotlin/org/opendc/compute/telemetry/table/HostTableReader.kt @@ -120,7 +120,7 @@ public interface HostTableReader { /** * The current temperature of the host in degrees Celsius. */ - public val temperature: Double + public val cpuTemperature: Double /** * The current carbon intensity of the host in gCO2 / kW. diff --git a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/TopologySpecs.kt b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/TopologySpecs.kt index bab394823..ec28c816d 100644 --- a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/TopologySpecs.kt +++ b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/TopologySpecs.kt @@ -58,6 +58,7 @@ public data class ClusterSpec( * @param memory The amount of RAM memory available in Byte * @param powerModel The power model used to determine the power draw of a host * @param count The power model used to determine the power draw of a host + * @param thermalModel The thermal model used to determine the temperature of a host - defaults to Intel Xeon Platinum 8160 */ @Serializable public data class HostJSONSpec( diff --git a/opendc-experiments/opendc-experiments-scenario/build.gradle.kts b/opendc-experiments/opendc-experiments-scenario/build.gradle.kts deleted file mode 100644 index f9d0add6e..000000000 --- a/opendc-experiments/opendc-experiments-scenario/build.gradle.kts +++ /dev/null @@ -1,97 +0,0 @@ - -/* - * Copyright (c) 2019 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -description = "Experiments for the Scenario work" - -// Build configuration -plugins { - `kotlin-library-conventions` - `kotlin-conventions` - `testing-conventions` - `jacoco-conventions` - `benchmark-conventions` - distribution - kotlin("plugin.serialization") version "1.9.22" -} - -dependencies { - implementation(projects.opendcSimulator.opendcSimulatorCore) - implementation(projects.opendcSimulator.opendcSimulatorCompute) - implementation(projects.opendcCompute.opendcComputeSimulator) - - implementation(libs.clikt) - implementation(libs.progressbar) - implementation(libs.kotlin.logging) - - implementation(libs.jackson.module.kotlin) - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0") - - implementation(project(mapOf("path" to ":opendc-compute:opendc-compute-telemetry"))) - implementation(project(mapOf("path" to ":opendc-compute:opendc-compute-topology"))) - implementation(project(mapOf("path" to ":opendc-compute:opendc-compute-workload"))) - implementation(project(mapOf("path" to ":opendc-experiments:opendc-experiments-base"))) - - runtimeOnly(libs.log4j.core) - runtimeOnly(libs.log4j.slf4j) -} - -val createScenarioApp by tasks.creating(CreateStartScripts::class) { - dependsOn(tasks.jar) - - applicationName = "scenario" - mainClass.set("org.opendc.experiments.scenario.ScenarioCli") - classpath = tasks.jar.get().outputs.files + configurations["runtimeClasspath"] - outputDir = project.buildDir.resolve("scripts") -} - -// Create custom Greenifier distribution -distributions { - main { - distributionBaseName.set("scenario") - - contents { - from("README.md") - from("LICENSE.txt") - from("../../LICENSE.txt") { - rename { "LICENSE-OpenDC.txt" } - } - - into("bin") { - from(createScenarioApp) - } - - into("lib") { - from(tasks.jar) - from(configurations["runtimeClasspath"]) - } - - into("resources") { - from("src/main/resources") - } - - into("Python_scripts") { - from("src/main/Python_scripts") - } - } - } -} diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java index cb22234dc..2ce54e792 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsu.java @@ -48,7 +48,7 @@ public abstract class SimPsu extends SimPowerInlet { /** * Return the temperature of the Host in degrees Celsius based on a power equation. */ - public abstract double getTemperature(); + public abstract double getCpuTemperature(); /** * Set the temperature of the Host in degrees Celsius based on a power equation. diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java index 53ac35ba7..82679ec31 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/SimPsuFactories.java @@ -93,7 +93,7 @@ public double getEnergyUsage() { } @Override - public double getTemperature() { + public double getCpuTemperature() { return 0; } @@ -182,7 +182,7 @@ public void setTemperature() { } @Override - public double getTemperature() { + public double getCpuTemperature() { return machineTemp; } diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModelFactories.kt b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModelFactories.kt index 188368d8d..bf46d0f08 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModelFactories.kt +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModelFactories.kt @@ -22,6 +22,19 @@ package org.opendc.simulator.compute.thermal +// FIXME: This currently only works for RC models, we need to generalize this to support more models. + +/** + * A factory for creating thermal models. + * @param modelType The type of the thermal model to create. + * @param rHS The thermal resistance between the heat source and the heat sink. + * @param rCase The thermal resistance between the heat sink and the ambient. + * @param minLeakageCurrent The minimum leakage current of the heat source. + * @param maxLeakageCurrent The maximum leakage current of the heat source. + * @param supplyVoltage The supply voltage of the heat source. + * @param ambientTemperature The ambient temperature of the heat source. + * @return The thermal model. + */ public fun getThermalModel( modelType: String, rHS: Double, @@ -42,10 +55,13 @@ public fun getThermalModel( ambientTemperature, ) - else -> throw IllegalArgumentException("Unknown power modelType $modelType") + else -> throw IllegalArgumentException("Unknown thermal modelType $modelType") } } +/** + * The default factory for creating RC thermal model using the values from an Intel Xeon Platinum 8160. + */ public fun getThermalModel(modelType: String): ThermalModel { return when (modelType) { "rcmodel" -> @@ -57,9 +73,7 @@ public fun getThermalModel(modelType: String): ThermalModel { 1.8, 22.0, ) - "manufacturerModel" -> - ThermalModels.manufacturerModel(0.278, 47.0) - else -> throw IllegalArgumentException("Unknown power modelType $modelType") + else -> throw IllegalArgumentException("Unknown thermal modelType $modelType") } } diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModels.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModels.java index f631553a0..97704dc08 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModels.java +++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/thermal/ThermalModels.java @@ -25,7 +25,12 @@ public class ThermalModels { public static ThermalModel rcmodel( - double rHS, double rCase, double minLeakageCurrent, double maxLeakageCurrent, double supplyVoltage, double ambientTemperature) { + double rHS, + double rCase, + double minLeakageCurrent, + double maxLeakageCurrent, + double supplyVoltage, + double ambientTemperature) { return new RCModel(rHS, rCase, minLeakageCurrent, maxLeakageCurrent, supplyVoltage, ambientTemperature); } @@ -61,8 +66,8 @@ private RCModel( private void setStaticPower(double dynamicPower, double minPower, double maxPower) { currentStaticPower = - ((maxLeakageCurrent - minLeakageCurrent) / (maxPower - minPower) * (dynamicPower - minPower)) - + minLeakageCurrent; + ((maxLeakageCurrent - minLeakageCurrent) / (maxPower - minPower) * (dynamicPower - minPower)) + + minLeakageCurrent; } private void setThermalPower(double dynamicPower, double minPower) { @@ -74,7 +79,7 @@ public double setTemperature(double dynamicPower, double minPower, double maxPow setStaticPower(dynamicPower, minPower, maxPower); setThermalPower(dynamicPower, minPower); - return ambientTemperature + (totalPowerDissipated * (rHS + rCase)); + return ambientTemperature + (totalPowerDissipated * (rHS + rCase)); } } diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/ThermalTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/ThermalTest.kt index d1ccc2c49..5018db145 100644 --- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/ThermalTest.kt +++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/ThermalTest.kt @@ -83,7 +83,7 @@ class ThermalTest { yield() assertAll({ assertEquals(expectedPower, machine.psu.thermalPower, 0.0001, "The power draw should be $expectedPower W") - assertEquals(expectedTemperature, machine.psu.temperature, 0.0001, "The temperature should be $expectedTemperature C") + assertEquals(expectedTemperature, machine.psu.cpuTemperature, 0.0001, "The temperature should be $expectedTemperature C") }) } } diff --git a/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt b/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt index d8257a5a2..37eb3c6b8 100644 --- a/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt +++ b/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt @@ -347,7 +347,15 @@ public class OpenDCRunner( val energyConsumptionW = machine.cpus.sumOf { it.energyConsumptionW } val powerModel = CpuPowerModels.linear(2 * energyConsumptionW, energyConsumptionW * 0.5) - val thermalModel = ThermalModels.rcmodel(0.298, 0.00061, 0.00035, 0.0041, 22.0) + val thermalModel = + ThermalModels.rcmodel( + 0.298, + 0.00061, + 0.00035, + 0.0041, + 1.8, + 22.0, + ) val spec = HostSpec(