From 85e8303f12b319e2eb231584324327f28d43fc2c Mon Sep 17 00:00:00 2001 From: Hongyu Date: Mon, 14 Jun 2021 13:37:52 +0200 Subject: simulator: Add Linux CPU frequency scaling governors This change adds the CPU frequency scaling governors that are found in the Linux kernel, which include the conservative and on-demand governor. --- .../simulator/compute/SimAbstractHypervisor.kt | 19 ++++++- .../compute/cpufreq/ConservativeScalingGovernor.kt | 65 ++++++++++++++++++++++ .../compute/cpufreq/OnDemandScalingGovernor.kt | 50 +++++++++++++++++ .../compute/cpufreq/PerformanceScalingGovernor.kt | 10 ++-- .../compute/cpufreq/PowerSaveScalingGovernor.kt | 36 ++++++++++++ .../simulator/compute/cpufreq/ScalingGovernor.kt | 6 +- .../simulator/compute/cpufreq/ScalingPolicy.kt | 51 +++++++++++++++++ .../simulator/compute/power/PStatePowerDriver.kt | 6 +- .../simulator/compute/power/SimplePowerDriver.kt | 4 +- 9 files changed, 231 insertions(+), 16 deletions(-) create mode 100644 opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ConservativeScalingGovernor.kt create mode 100644 opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/OnDemandScalingGovernor.kt create mode 100644 opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/PowerSaveScalingGovernor.kt create mode 100644 opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ScalingPolicy.kt (limited to 'opendc-simulator/opendc-simulator-compute/src/main') diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimAbstractHypervisor.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimAbstractHypervisor.kt index 57c25b86..d24ed1f3 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimAbstractHypervisor.kt +++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/SimAbstractHypervisor.kt @@ -23,6 +23,7 @@ package org.opendc.simulator.compute import org.opendc.simulator.compute.cpufreq.ScalingGovernor +import org.opendc.simulator.compute.cpufreq.ScalingPolicy import org.opendc.simulator.compute.interference.PerformanceInterferenceModel import org.opendc.simulator.compute.model.ProcessingUnit import org.opendc.simulator.resources.* @@ -100,11 +101,12 @@ public abstract class SimAbstractHypervisor( switch = createSwitch(ctx) for (cpu in ctx.cpus) { - val governor = scalingGovernor?.createLogic(cpu) + val governor = scalingGovernor?.createLogic(ScalingPolicyImpl(cpu)) if (governor != null) { governors.add(governor) governor.onStart() } + switch.addInput(cpu) } } @@ -146,4 +148,19 @@ public abstract class SimAbstractHypervisor( override fun toString(): String = "SimAbstractHypervisor.VCpu[model=$model]" } + + /** + * A [ScalingPolicy] for a physical CPU of the hypervisor. + */ + private class ScalingPolicyImpl(override val cpu: SimProcessingUnit) : ScalingPolicy { + override var target: Double + get() = cpu.capacity + set(value) { + cpu.capacity = value + } + + override val max: Double = cpu.model.frequency + + override val min: Double = 0.0 + } } diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ConservativeScalingGovernor.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ConservativeScalingGovernor.kt new file mode 100644 index 00000000..562c0b73 --- /dev/null +++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ConservativeScalingGovernor.kt @@ -0,0 +1,65 @@ +/* + * 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 + +/** + * A CPUFreq [ScalingGovernor] that models the conservative scaling governor in the Linux kernel. + */ +public class ConservativeScalingGovernor(public val threshold: Double = 0.8, private val stepSize: Double = -1.0) : ScalingGovernor { + override fun createLogic(policy: ScalingPolicy): ScalingGovernor.Logic = object : ScalingGovernor.Logic { + /** + * The step size to use. + */ + private val stepSize = if (this@ConservativeScalingGovernor.stepSize < 0) { + // https://github.com/torvalds/linux/blob/master/drivers/cpufreq/cpufreq_conservative.c#L33 + policy.max * 0.05 + } else { + this@ConservativeScalingGovernor.stepSize.coerceAtMost(policy.max) + } + + /** + * The previous load of the CPU. + */ + private var previousLoad = threshold + + override fun onStart() { + policy.target = policy.min + } + + override fun onLimit(load: Double) { + val currentTarget = policy.target + if (load > threshold) { + // Check for load increase (see: https://github.com/torvalds/linux/blob/master/drivers/cpufreq/cpufreq_conservative.c#L102) + val step = when { + load > previousLoad -> stepSize + load < previousLoad -> -stepSize + else -> 0.0 + } + policy.target = (currentTarget + step).coerceIn(policy.min, policy.max) + } + previousLoad = load + } + } + + override fun toString(): String = "ConservativeScalingGovernor[threshold=$threshold,stepSize=$stepSize]" +} diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/OnDemandScalingGovernor.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/OnDemandScalingGovernor.kt new file mode 100644 index 00000000..2c4a83f1 --- /dev/null +++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/OnDemandScalingGovernor.kt @@ -0,0 +1,50 @@ +/* + * 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 + +/** + * A CPUFreq [ScalingGovernor] that models the on-demand scaling governor in the Linux kernel. + */ +public class OnDemandScalingGovernor(public val threshold: Double = 0.8) : ScalingGovernor { + override fun createLogic(policy: ScalingPolicy): ScalingGovernor.Logic = object : ScalingGovernor.Logic { + /** + * The multiplier used for the linear frequency scaling. + */ + private val multiplier = (policy.max - policy.min) / 100 + + override fun onStart() { + policy.target = policy.min + } + + override fun onLimit(load: Double) { + policy.target = if (load < threshold) { + /* Proportional scaling (see: https://github.com/torvalds/linux/blob/master/drivers/cpufreq/cpufreq_ondemand.c#L151). */ + policy.min + load * multiplier + } else { + policy.max + } + } + } + + override fun toString(): String = "OnDemandScalingGovernor[threshold=$threshold]" +} diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/PerformanceScalingGovernor.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/PerformanceScalingGovernor.kt index 245877be..8b1d49f6 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/PerformanceScalingGovernor.kt +++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/PerformanceScalingGovernor.kt @@ -22,17 +22,15 @@ package org.opendc.simulator.compute.cpufreq -import org.opendc.simulator.compute.SimProcessingUnit - /** * A CPUFreq [ScalingGovernor] that causes the highest possible frequency to be requested from the resource. */ public class PerformanceScalingGovernor : ScalingGovernor { - override fun createLogic(cpu: SimProcessingUnit): ScalingGovernor.Logic = object : ScalingGovernor.Logic { + override fun createLogic(policy: ScalingPolicy): ScalingGovernor.Logic = object : ScalingGovernor.Logic { override fun onStart() { - cpu.capacity = cpu.model.frequency + policy.target = policy.max } - - override fun toString(): String = "PerformanceScalingGovernor.Logic" } + + override fun toString(): String = "PerformanceScalingGovernor" } diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/PowerSaveScalingGovernor.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/PowerSaveScalingGovernor.kt new file mode 100644 index 00000000..0889980c --- /dev/null +++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/PowerSaveScalingGovernor.kt @@ -0,0 +1,36 @@ +/* + * 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 + +/** + * A CPUFreq [ScalingGovernor] that causes the lowest possible frequency to be requested from the resource. + */ +public class PowerSaveScalingGovernor : ScalingGovernor { + override fun createLogic(policy: ScalingPolicy): ScalingGovernor.Logic = object : ScalingGovernor.Logic { + override fun onStart() { + policy.target = policy.min + } + } + + override fun toString(): String = "PowerSaveScalingGovernor" +} diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ScalingGovernor.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ScalingGovernor.kt index b7e7ffc6..3fb93ad9 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ScalingGovernor.kt +++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ScalingGovernor.kt @@ -22,8 +22,6 @@ package org.opendc.simulator.compute.cpufreq -import org.opendc.simulator.compute.SimProcessingUnit - /** * A [ScalingGovernor] in the CPUFreq subsystem of OpenDC is responsible for scaling the frequency of simulated CPUs * independent of the particular implementation of the CPU. @@ -35,9 +33,9 @@ import org.opendc.simulator.compute.SimProcessingUnit */ public interface ScalingGovernor { /** - * Create the scaling logic for the specified [cpu] + * Create the scaling logic for the specified [policy] */ - public fun createLogic(cpu: SimProcessingUnit): Logic + public fun createLogic(policy: ScalingPolicy): Logic /** * The logic of the scaling governor. diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ScalingPolicy.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ScalingPolicy.kt new file mode 100644 index 00000000..0552d279 --- /dev/null +++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/cpufreq/ScalingPolicy.kt @@ -0,0 +1,51 @@ +/* + * 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 org.opendc.simulator.compute.SimProcessingUnit + +/** + * An interface that holds the state managed by a [ScalingGovernor] and used by the underlying machine to control the + * CPU frequencies. + */ +public interface ScalingPolicy { + /** + * The processing unit that is associated with this policy. + */ + public val cpu: SimProcessingUnit + + /** + * The target frequency which the CPU should attempt to attain. + */ + public var target: Double + + /** + * The minimum frequency to which the CPU may scale. + */ + public val min: Double + + /** + * The maximum frequency to which the CPU may scale. + */ + public val max: Double +} diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/power/PStatePowerDriver.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/power/PStatePowerDriver.kt index 6328c8e4..6577fbfc 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/power/PStatePowerDriver.kt +++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/power/PStatePowerDriver.kt @@ -37,7 +37,7 @@ public class PStatePowerDriver(states: Map) : PowerDriver { /** * The P-States defined by the user and ordered by key. */ - private val states = TreeMap(states) + private val states: TreeMap = TreeMap(states) override fun createLogic(machine: SimMachine, cpus: List): PowerDriver.Logic = object : PowerDriver.Logic { override fun computePower(): Double { @@ -54,7 +54,7 @@ public class PStatePowerDriver(states: Map) : PowerDriver { val utilization = totalSpeed / (actualFreq * cpus.size) return model.computePower(utilization) } - - override fun toString(): String = "PStatePowerDriver.Logic" } + + override fun toString(): String = "PStatePowerDriver[states=$states]" } diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/power/SimplePowerDriver.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/power/SimplePowerDriver.kt index 5c5ceff5..e43c89ac 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/power/SimplePowerDriver.kt +++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/power/SimplePowerDriver.kt @@ -33,7 +33,7 @@ public class SimplePowerDriver(private val model: PowerModel) : PowerDriver { override fun computePower(): Double { return model.computePower(machine.usage.value) } - - override fun toString(): String = "SimplePowerDriver.Logic" } + + override fun toString(): String = "SimplePowerDriver[model=$model]" } -- cgit v1.2.3