#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
+SIMGRID_REGISTER_PLUGIN(host_energy, "Cpu energy consumption.", &sg_host_energy_plugin_init)
+
/** @addtogroup plugin_energy
This is the energy plugin, enabling to account not only for computation time, but also for the dissipated energy in the
As a result, our energy model takes 4 parameters:
- - \b Idle: instantaneous consumption (in Watt) when your host is up and running, but without anything to do.
- - \b OneCore: instantaneous consumption (in Watt) when only one core is active, at 100%.
- - \b AllCores: instantaneous consumption (in Watt) when all cores of the host are at 100%.
- - \b Off: instantaneous consumption (in Watt) when the host is turned off.
+ - @b Idle: instantaneous consumption (in Watt) when your host is up and running, but without anything to do.
+ - @b OneCore: instantaneous consumption (in Watt) when only one core is active, at 100%.
+ - @b AllCores: instantaneous consumption (in Watt) when all cores of the host are at 100%.
+ - @b Off: instantaneous consumption (in Watt) when the host is turned off.
Here is an example of XML declaration:
-\code{.xml}
+@code{.xml}
<host id="HostA" power="100.0Mf" cores="4">
<prop id="watt_per_state" value="100.0:120.0:200.0" />
<prop id="watt_off" value="10" />
</host>
-\endcode
+@endcode
-This example gives the following parameters: \b Off is 10 Watts; \b Idle is 100 Watts; \b OneCore is 120 Watts and \b
+This example gives the following parameters: @b Off is 10 Watts; @b Idle is 100 Watts; @b OneCore is 120 Watts and @b
AllCores is 200 Watts.
This is enough to compute the consumption as a function of the amount of loaded cores:
<table>
-<tr><th>\#Cores loaded</th><th>Consumption</th><th>Explanation</th></tr>
+<tr><th>@#Cores loaded</th><th>Consumption</th><th>Explanation</th></tr>
<tr><td>0</td><td> 100 Watts</td><td>Idle value</td></tr>
<tr><td>1</td><td> 120 Watts</td><td>OneCore value</td></tr>
<tr><td>2</td><td> 147 Watts</td><td>linear extrapolation between OneCore and AllCores</td></tr>
### What if the host has only one core?
-In this case, the parameters \b OneCore and \b AllCores are obviously the same.
+In this case, the parameters @b OneCore and @b AllCores are obviously the same.
Actually, SimGrid expect an energetic profile formatted as 'Idle:Running' for mono-cores hosts.
-If you insist on passing 3 parameters in this case, then you must have the same value for \b OneCore and \b AllCores.
+If you insist on passing 3 parameters in this case, then you must have the same value for @b OneCore and @b AllCores.
-\code{.xml}
+@code{.xml}
<host id="HostC" power="100.0Mf" cores="1">
<prop id="watt_per_state" value="95.0:200.0" /> <!-- we may have used '95:200:200' instead -->
<prop id="watt_off" value="10" />
</host>
-\endcode
+@endcode
### How does DVFS interact with the host energy model?
If your host has several DVFS levels (several pstates), then you should give the energetic profile of each pstate level:
-\code{.xml}
+@code{.xml}
<host id="HostC" power="100.0Mf,50.0Mf,20.0Mf" cores="4">
<prop id="watt_per_state" value="95.0:120.0:200.0, 93.0:115.0:170.0, 90.0:110.0:150.0" />
<prop id="watt_off" value="10" />
</host>
-\endcode
+@endcode
This encodes the following values
<table>
{
double start_time = this->last_updated_;
double finish_time = surf_get_clock();
-
+ //
+ // We may have start == finish if the past consumption was updated since the simcall was started
+ // for example if 2 actors requested to update the same host's consumption in a given scheduling round.
+ //
+ // Even in this case, we need to save the pstate for the next call (after this if),
+ // which may have changed since that recent update.
if (start_time < finish_time) {
double previous_energy = this->total_energy_;
this->total_energy_ = previous_energy + energy_this_step;
this->last_updated_ = finish_time;
- XBT_DEBUG("[update_energy of %s] period=[%.2f-%.2f]; current power peak=%.0E flop/s; consumption change: %.2f J -> "
- "%.2f J",
- host_->get_cname(), start_time, finish_time, host_->pimpl_cpu->get_speed(1.0), previous_energy,
+ XBT_DEBUG("[update_energy of %s] period=[%.8f-%.8f]; current speed=%.2E flop/s (pstate %i); total consumption before: consumption change: %.8f J -> added now: %.8f J",
+ host_->get_cname(), start_time, finish_time, host_->pimpl_cpu->get_pstate_peak_speed(this->pstate_), this->pstate_, previous_energy,
energy_this_step);
}
double current_speed = host_->get_speed();
double cpu_load;
- // We may have start == finish if the past consumption was updated since the simcall was started
- // for example if 2 actors requested to update the same host's consumption in a given scheduling round.
- //
- // Even in this case, we need to save the pstate for the next call (after this big if),
- // which may have changed since that recent update.
if (current_speed <= 0)
// Some users declare a pstate of speed 0 flops (e.g., to model boot time).
current_power = range.idle_;
}
- XBT_DEBUG("[get_current_watts] min_power=%f, max_power=%f, slope=%f", min_power, max_power, power_slope);
+ XBT_DEBUG("[get_current_watts] pstate=%i, min_power=%f, max_power=%f, slope=%f", this->pstate_, min_power, max_power, power_slope);
XBT_DEBUG("[get_current_watts] Current power (watts) = %f, load = %f", current_power, cpu_load);
return current_power;
// In this case, 1core == AllCores
current_power_values.push_back(current_power_values.at(1));
} else { // size == 3
- xbt_assert((current_power_values.at(1)) == (current_power_values.at(2)),
- "Power properties incorrectly defined for host %s.\n"
- "The energy profile of mono-cores should be formatted as 'Idle:FullSpeed' only.\n"
- "If you go for a 'Idle:OneCore:AllCores' power profile on mono-cores, then OneCore and AllCores "
- "must be equal.",
- host_->get_cname());
+ current_power_values[2] = current_power_values.at(1);
+ static thread_local bool displayed_warning = false;
+ if (not displayed_warning) { // Otherwise we get in the worst case no_pstate*no_hosts warnings
+ XBT_WARN("Host %s is a single-core machine and part of the power profile is '%s'"
+ ", which is in the 'Idle:OneCore:AllCores' format."
+ " Since this is a single-core machine, AllCores and OneCore are identical."
+ " Here, only the value for 'OneCore' is used.", host_->get_cname(), current_power_values_str.c_str());
+ displayed_warning = true;
+ }
}
} else {
xbt_assert(current_power_values.size() == 3,
/* **************************** Public interface *************************** */
-/** \ingroup plugin_energy
- * \brief Enable host energy plugin
- * \details Enable energy plugin to get joules consumption of each cpu. Call this function before #MSG_init().
+/** @ingroup plugin_energy
+ * @brief Enable host energy plugin
+ * @details Enable energy plugin to get joules consumption of each cpu. Call this function before #MSG_init().
*/
void sg_host_energy_plugin_init()
{