#include <simgrid/s4u/VirtualMachine.hpp>
#include <simgrid/simix.hpp>
+#include "src/kernel/activity/ActivityImpl.hpp"
#include "src/kernel/resource/CpuImpl.hpp"
+#include "src/simgrid/module.hpp"
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
<table border="1">
<tr><th>#Cores loaded</th><th>Wattage</th><th>Explanation</th></tr>
- <tr><td>0 (idle)</td><td> 100 Watts </td><td> Idle value</td></tr>
- <tr><td>0 (not idle)</td><td> 120 Watts</td><td> Epsilon value</td></tr>
+ <tr><td>0 (idle)</td><td> 100 Watts </td><td>Idle value</td></tr>
<tr><td>1</td><td> 140 Watts</td><td> Linear extrapolation between Epsilon and AllCores</td></tr>
<tr><td>2</td><td> 160 Watts</td><td> Linear extrapolation between Epsilon and AllCores</td></tr>
<tr><td>3</td><td> 180 Watts</td><td> Linear extrapolation between Epsilon and AllCores</td></tr>
<tr><td>4</td><td> 200 Watts</td><td> AllCores value</td></tr>
</table>
+Here is how it looks graphically:
+
+.. image:: img/plugin-energy.svg
+ :scale: 80%
+ :align: center
+
+As you can see, the ``Epsilon`` parameter allows to freely specify the slope you want, while using the 2 parameters
+version of the model (with only ``Idle`` and ``AllCores``) requires that the ``Idle`` value is on the extension of the
+line crossing the consumption you mesure for each core amount. Please note that specifying the consumption for each core
+amount separately was not a solution because parallel tasks can use an amount of cores that is not an integer. The good
+news is that it was not necessary, as our experiments (detailed in the paper) show that the proposed linear model is
+sufficient to capture reality.
.. raw:: html
static void on_action_state_change(simgrid::kernel::resource::CpuAction const& action,
simgrid::kernel::resource::Action::State /*previous*/)
{
- for (simgrid::kernel::resource::CpuImpl* const& cpu : action.cpus()) {
+ for (simgrid::kernel::resource::CpuImpl const* cpu : action.cpus()) {
simgrid::s4u::Host* host = cpu->get_iface();
if (host != nullptr) {
// If it's a VM, take the corresponding PM
/* This callback is fired either when the host changes its state (on/off) ("onStateChange") or its speed
* (because the user changed the pstate, or because of external trace events) ("onSpeedChange") */
-static void on_host_change(simgrid::s4u::Host const& host)
+static void on_host_change(simgrid::s4u::Host const& h)
{
- if (dynamic_cast<simgrid::s4u::VirtualMachine const*>(&host)) // Ignore virtual machines
- return;
+ const auto* host = &h;
+ if (const auto* vm = dynamic_cast<simgrid::s4u::VirtualMachine const*>(host)) // Take the PM of virtual machines
+ host = vm->get_pm();
- auto* host_energy = host.extension<HostEnergy>();
-
- host_energy->update();
+ host->extension<HostEnergy>()->update();
}
static void on_host_destruction(simgrid::s4u::Host const& host)
used_hosts_energy, total_energy - used_hosts_energy);
}
+static void on_activity_suspend_resume(simgrid::s4u::Activity const& activity)
+{
+ if (const auto* action = dynamic_cast<simgrid::kernel::resource::CpuAction*>(activity.get_impl()->model_action_))
+ on_action_state_change(*action, /*ignored*/ action->get_state());
+}
+
/* **************************** Public interface *************************** */
/** @ingroup plugin_host_energy
HostEnergy::EXTENSION_ID = simgrid::s4u::Host::extension_create<HostEnergy>();
simgrid::s4u::Host::on_creation_cb(&on_creation);
- simgrid::s4u::Host::on_state_change_cb(&on_host_change);
+ simgrid::s4u::Host::on_onoff_cb(&on_host_change);
simgrid::s4u::Host::on_speed_change_cb(&on_host_change);
simgrid::s4u::Host::on_destruction_cb(&on_host_destruction);
+ simgrid::s4u::Host::on_exec_state_change_cb(&on_action_state_change);
+ simgrid::s4u::VirtualMachine::on_suspend_cb(&on_host_change);
+ simgrid::s4u::VirtualMachine::on_resume_cb(&on_host_change);
+ simgrid::s4u::Exec::on_suspend_cb(on_activity_suspend_resume);
+ simgrid::s4u::Exec::on_resume_cb(on_activity_suspend_resume);
simgrid::s4u::Engine::on_simulation_end_cb(&on_simulation_end);
- simgrid::kernel::resource::CpuAction::on_state_change.connect(&on_action_state_change);
// We may only have one actor on a node. If that actor executes something like
// compute -> recv -> compute
- // the recv operation will not trigger a "CpuAction::on_state_change". This means
+ // the recv operation will not trigger a "Host::on_exec_state_change_cb". This means
// that the next trigger would be the 2nd compute, hence ignoring the idle time
// during the recv call. By updating at the beginning of a compute, we can
// fix that. (If the cpu is not idle, this is not required.)
simgrid::s4u::Exec::on_start_cb([](simgrid::s4u::Exec const& activity) {
if (activity.get_host_number() == 1) { // We only run on one host
- simgrid::s4u::Host* host = activity.get_host();
+ simgrid::s4u::Host* host = activity.get_host();
if (const auto* vm = dynamic_cast<simgrid::s4u::VirtualMachine*>(host))
host = vm->get_pm();
xbt_assert(host != nullptr);
double sg_host_get_consumed_energy(const_sg_host_t host)
{
ensure_plugin_inited();
- auto host_energy = host->extension<HostEnergy>();
+ auto* host_energy = host->extension<HostEnergy>();
xbt_assert(host_energy->has_pstate_power_values(), "No power range properties specified for host %s",
host->get_cname());
return host_energy->get_consumed_energy();
double sg_host_get_current_consumption(const_sg_host_t host)
{
ensure_plugin_inited();
- auto host_energy = host->extension<HostEnergy>();
+ auto* host_energy = host->extension<HostEnergy>();
xbt_assert(host_energy->has_pstate_power_values(), "No power range properties specified for host %s",
host->get_cname());
return host_energy->get_current_watts_value();