diff options
Diffstat (limited to 'simulator')
6 files changed, 209 insertions, 10 deletions
diff --git a/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/PStateScalingDriver.kt b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/PStateScalingDriver.kt index 8f3eacea..d109e4d8 100644 --- a/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/PStateScalingDriver.kt +++ b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/PStateScalingDriver.kt @@ -28,6 +28,7 @@ import org.opendc.simulator.compute.power.PowerModel import org.opendc.simulator.resources.SimResourceSource import java.util.* import kotlin.math.max +import kotlin.math.min /** * A [ScalingDriver] that scales the frequency of the processor based on a discrete set of frequencies. @@ -53,18 +54,18 @@ public class PStateScalingDriver(states: Map<Double, PowerModel>) : ScalingDrive } override fun computePower(): Double { - var freq = 0.0 + var targetFreq = 0.0 var totalSpeed = 0.0 - var totalFreq = 0.0 for (ctx in contexts) { - freq = max(ctx.target, freq) + targetFreq = max(ctx.target, targetFreq) totalSpeed += ctx.resource.speed.value - totalFreq += ctx.target } - val (_, model) = states.ceilingEntry(freq) - return model.computePower(totalSpeed / totalFreq) + val maxFreq = states.lastKey() + val (actualFreq, model) = states.ceilingEntry(min(maxFreq, targetFreq)) + val utilization = totalSpeed / (actualFreq * contexts.size) + return model.computePower(utilization) } override fun toString(): String = "PStateScalingDriver.Logic" diff --git a/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ScalingGovernor.kt b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ScalingGovernor.kt index 9c6eb9ed..c9aea580 100644 --- a/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ScalingGovernor.kt +++ b/simulator/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ScalingGovernor.kt @@ -47,7 +47,7 @@ public interface ScalingGovernor { public fun onStart() {} /** - * This method is invoked when + * This method is invoked when the governor should re-decide the frequency limits. */ public fun onLimit() {} } diff --git a/simulator/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt b/simulator/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt index 13f7f9ea..d947b9cb 100644 --- a/simulator/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt +++ b/simulator/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt @@ -28,6 +28,8 @@ import kotlinx.coroutines.test.runBlockingTest import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertDoesNotThrow +import org.junit.jupiter.api.assertThrows import org.opendc.simulator.compute.cpufreq.PerformanceScalingGovernor import org.opendc.simulator.compute.cpufreq.SimpleScalingDriver import org.opendc.simulator.compute.model.MemoryUnit @@ -86,4 +88,14 @@ class SimMachineTest { machine.close() } } + + @Test + fun testClose() = runBlockingTest { + val clock = DelayControllerClockAdapter(this) + val machine = SimBareMetalMachine(coroutineContext, clock, machineModel, PerformanceScalingGovernor(), SimpleScalingDriver(ConstantPowerModel(0.0))) + + machine.close() + assertDoesNotThrow { machine.close() } + assertThrows<IllegalStateException> { machine.run(SimFlopsWorkload(2_000, utilization = 1.0)) } + } } diff --git a/simulator/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/cpufreq/DemandScalingGovernorTest.kt b/simulator/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/cpufreq/DemandScalingGovernorTest.kt new file mode 100644 index 00000000..19c06126 --- /dev/null +++ b/simulator/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/cpufreq/DemandScalingGovernorTest.kt @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021 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.cpufreq + +import io.mockk.every +import io.mockk.mockk +import io.mockk.verify +import org.junit.jupiter.api.Test + +/** + * Test suite for the [DemandScalingGovernor] + */ +internal class DemandScalingGovernorTest { + @Test + fun testSetDemandLimit() { + val ctx = mockk<ScalingContext>(relaxUnitFun = true) + + every { ctx.resource.speed.value } returns 2100.0 + + val logic = DemandScalingGovernor().createLogic(ctx) + + logic.onStart() + verify(exactly = 0) { ctx.setTarget(any()) } + + logic.onLimit() + verify(exactly = 1) { ctx.setTarget(2100.0) } + } +} diff --git a/simulator/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/cpufreq/PStateScalingDriverTest.kt b/simulator/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/cpufreq/PStateScalingDriverTest.kt new file mode 100644 index 00000000..5c30bc1f --- /dev/null +++ b/simulator/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/cpufreq/PStateScalingDriverTest.kt @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2021 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.cpufreq + +import io.mockk.every +import io.mockk.mockk +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.opendc.simulator.compute.SimBareMetalMachine +import org.opendc.simulator.compute.model.ProcessingUnit +import org.opendc.simulator.compute.power.ConstantPowerModel +import org.opendc.simulator.compute.power.LinearPowerModel +import org.opendc.simulator.resources.SimResourceSource + +/** + * Test suite for [PStateScalingDriver]. + */ +internal class PStateScalingDriverTest { + @Test + fun testPowerWithoutGovernor() { + val machine = mockk<SimBareMetalMachine>() + + val driver = PStateScalingDriver( + sortedMapOf( + 2800.0 to ConstantPowerModel(200.0), + 3300.0 to ConstantPowerModel(300.0), + 3600.0 to ConstantPowerModel(350.0), + ) + ) + + val logic = driver.createLogic(machine) + assertEquals(200.0, logic.computePower()) + } + + @Test + fun testPowerWithSingleGovernor() { + val machine = mockk<SimBareMetalMachine>() + val cpu = mockk<ProcessingUnit>() + val resource = mockk<SimResourceSource>() + + every { cpu.frequency } returns 4100.0 + every { resource.speed.value } returns 1200.0 + + val driver = PStateScalingDriver( + sortedMapOf( + 2800.0 to ConstantPowerModel(200.0), + 3300.0 to ConstantPowerModel(300.0), + 3600.0 to ConstantPowerModel(350.0), + ) + ) + + val logic = driver.createLogic(machine) + + val scalingContext = logic.createContext(cpu, resource) + scalingContext.setTarget(3200.0) + + assertEquals(300.0, logic.computePower()) + } + + @Test + fun testPowerWithMultipleGovernors() { + val machine = mockk<SimBareMetalMachine>() + val cpu = mockk<ProcessingUnit>() + val resource = mockk<SimResourceSource>() + + every { cpu.frequency } returns 4100.0 + every { resource.speed.value } returns 1200.0 + + val driver = PStateScalingDriver( + sortedMapOf( + 2800.0 to ConstantPowerModel(200.0), + 3300.0 to ConstantPowerModel(300.0), + 3600.0 to ConstantPowerModel(350.0), + ) + ) + + val logic = driver.createLogic(machine) + + val scalingContextA = logic.createContext(cpu, resource) + scalingContextA.setTarget(1000.0) + + val scalingContextB = logic.createContext(cpu, resource) + scalingContextB.setTarget(3400.0) + + assertEquals(350.0, logic.computePower()) + } + + @Test + fun testPowerBasedOnUtilization() { + val machine = mockk<SimBareMetalMachine>() + val cpu = mockk<ProcessingUnit>() + val resource = mockk<SimResourceSource>() + + every { cpu.frequency } returns 4200.0 + + val driver = PStateScalingDriver( + sortedMapOf( + 2800.0 to LinearPowerModel(200.0, 100.0), + 3300.0 to LinearPowerModel(250.0, 150.0), + 4000.0 to LinearPowerModel(300.0, 200.0), + ) + ) + + val logic = driver.createLogic(machine) + + val scalingContext = logic.createContext(cpu, resource) + + every { resource.speed.value } returns 1400.0 + scalingContext.setTarget(1400.0) + assertEquals(150.0, logic.computePower()) + + every { resource.speed.value } returns 1400.0 + scalingContext.setTarget(4000.0) + assertEquals(235.0, logic.computePower()) + } +} diff --git a/simulator/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/power/PowerModelTest.kt b/simulator/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/power/PowerModelTest.kt index 8ec9910c..439be274 100644 --- a/simulator/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/power/PowerModelTest.kt +++ b/simulator/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/power/PowerModelTest.kt @@ -3,7 +3,6 @@ package org.opendc.simulator.compute.power import org.junit.jupiter.api.Assertions.assertAll import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertThrows import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.MethodSource @@ -31,8 +30,11 @@ internal class PowerModelTest { expectedPowerConsumption: Double ) { val zeroPowerModel = ZeroIdlePowerDecorator(powerModel) - val computedPowerConsumption = zeroPowerModel.computePower(0.0) - assertEquals(0.0, computedPowerConsumption) + + assertAll( + { assertEquals(expectedPowerConsumption, zeroPowerModel.computePower(cpuUtil), epsilon) }, + { assertEquals(0.0, zeroPowerModel.computePower(0.0)) } + ) } @Test |
