X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/4386010688d60bea7f54c2383aa9c923f2980948..1847d1441271d076b3de449c8853031ea208ce8f:/src/surf/plugins/host_energy.cpp
diff --git a/src/surf/plugins/host_energy.cpp b/src/surf/plugins/host_energy.cpp
index 85d3d0c49d..6e102e470e 100644
--- a/src/surf/plugins/host_energy.cpp
+++ b/src/surf/plugins/host_energy.cpp
@@ -18,16 +18,14 @@
/** @addtogroup plugin_energy
-
-This is the energy plugin, enabling to account not only for computation time,
-but also for the dissipated energy in the simulated platform.
-To activate this plugin, first call sg_host_energy_plugin_init() before your #MSG_init(),
-and then use MSG_host_get_consumed_energy() to retrieve the consumption of a given host.
-
-When the host is on, this energy consumption naturally depends on both the
-current CPU load and the host energy profile. According to our measurements,
-the consumption is somehow linear in the amount of cores at full speed,
-with an abnormality when all the cores are idle. The full details are in
+This is the energy plugin, enabling to account not only for computation time, but also for the dissipated energy in the
+simulated platform.
+To activate this plugin, first call sg_host_energy_plugin_init() before your #MSG_init(), and then use
+MSG_host_get_consumed_energy() to retrieve the consumption of a given host.
+
+When the host is on, this energy consumption naturally depends on both the current CPU load and the host energy profile.
+According to our measurements, the consumption is somehow linear in the amount of cores at full speed, with an
+abnormality when all the cores are idle. The full details are in
our scientific paper on that topic.
As a result, our energy model takes 4 parameters:
@@ -61,15 +59,14 @@ This is enough to compute the consumption as a function of the amount of loaded
### What if a given core is only at load 50%?
-This is impossible in SimGrid because we recompute everything each time
-that the CPU starts or stops doing something. So if a core is at load 50% over
-a period, it means that it is at load 100% half of the time and at load 0% the
-rest of the time, and our model holds.
+This is impossible in SimGrid because we recompute everything each time that the CPU starts or stops doing something.
+So if a core is at load 50% over a period, it means that it is at load 100% half of the time and at load 0% the rest of
+the time, and our model holds.
### What if the host has only one core?
In this case, the parameters \b OneCore and \b AllCores are obviously the same.
-Actually, SimGrid expect an energetic profile formated as 'Idle:Running' for mono-cores hosts.
+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.
\code{.xml}
@@ -81,8 +78,7 @@ If you insist on passing 3 parameters in this case, then you must have the same
### 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:
+If your host has several DVFS levels (several pstates), then you should give the energetic profile of each pstate level:
\code{.xml}
@@ -104,14 +100,11 @@ To change the pstate of a given CPU, use the following functions:
### How accurate are these models?
-This model cannot be more accurate than your instantiation:
-with the default values, your result will not be accurate at all. You can still get
-accurate energy prediction, provided that you carefully instantiate the model.
-The first step is to ensure that your timing prediction match perfectly. But this
-is only the first step of the path, and you really want to read
-this paper to see all what you need
-to do before you can get accurate energy predictions.
-
+This model cannot be more accurate than your instantiation: with the default values, your result will not be accurate at
+all. You can still get accurate energy prediction, provided that you carefully instantiate the model.
+The first step is to ensure that your timing prediction match perfectly. But this is only the first step of the path,
+and you really want to read this paper to see all what you need to do
+before you can get accurate energy predictions.
*/
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_energy, surf, "Logging specific to the SURF energy plugin");
@@ -147,11 +140,11 @@ private:
std::vector
power_range_watts_list; /*< List of (min_power,max_power) pairs corresponding to each cpu pstate */
- /* We need to keep track of what pstate has been used, as we will sometimes
- * be notified only *after* a pstate has been used (but we need to update the energy consumption
- * with the old pstate!)
+ /* We need to keep track of what pstate has been used, as we will sometimes be notified only *after* a pstate has been
+ * used (but we need to update the energy consumption with the old pstate!)
*/
int pstate = 0;
+ const int pstate_off = -1;
public:
double watts_off = 0.0; /*< Consumption when the machine is turned off (shutdown) */
@@ -161,12 +154,12 @@ public:
simgrid::xbt::Extension HostEnergy::EXTENSION_ID;
-/* Computes the consumption so far. Called lazily on need. */
+/* Computes the consumption so far. Called lazily on need. */
void HostEnergy::update()
{
double start_time = this->last_updated;
double finish_time = surf_get_clock();
- double current_speed = host->speed();
+ double current_speed = host->getSpeed();
if (start_time < finish_time) {
double cpu_load;
@@ -200,7 +193,7 @@ void HostEnergy::update()
double previous_energy = this->total_energy;
double instantaneous_consumption;
- if (this->pstate == -1) // The host was off at the beginning of this time interval
+ if (this->pstate == pstate_off) // The host was off at the beginning of this time interval
instantaneous_consumption = this->watts_off;
else
instantaneous_consumption = this->getCurrentWattsValue(cpu_load);
@@ -214,22 +207,26 @@ void HostEnergy::update()
XBT_DEBUG("[update_energy of %s] period=[%.2f-%.2f]; current power peak=%.0E flop/s; consumption change: %.2f J -> "
"%.2f J",
- host->cname(), start_time, finish_time, host->pimpl_cpu->speed_.peak, previous_energy, energy_this_step);
+ host->getCname(), start_time, finish_time, host->pimpl_cpu->speed_.peak, previous_energy,
+ energy_this_step);
}
/* Save data for the upcoming time interval: whether it's on/off and the pstate if it's on */
- this->pstate = host->isOn() ? host->pstate() : -1;
+ this->pstate = host->isOn() ? host->getPstate() : pstate_off;
}
HostEnergy::HostEnergy(simgrid::s4u::Host* ptr) : host(ptr), last_updated(surf_get_clock())
{
initWattsRangeList();
- const char* off_power_str = host->property("watt_off");
+ const char* off_power_str = host->getProperty("watt_off");
if (off_power_str != nullptr) {
- char* msg = bprintf("Invalid value for property watt_off of host %s: %%s", host->cname());
- this->watts_off = xbt_str_parse_double(off_power_str, msg);
- xbt_free(msg);
+ try {
+ this->watts_off = std::stod(std::string(off_power_str));
+ } catch (std::invalid_argument& ia) {
+ throw std::invalid_argument(std::string("Invalid value for property watt_off of host ") + host->getCname() +
+ ": " + off_power_str);
+ }
}
/* watts_off is 0 by default */
}
@@ -238,20 +235,20 @@ HostEnergy::~HostEnergy() = default;
double HostEnergy::getWattMinAt(int pstate)
{
- xbt_assert(not power_range_watts_list.empty(), "No power range properties specified for host %s", host->cname());
+ xbt_assert(not power_range_watts_list.empty(), "No power range properties specified for host %s", host->getCname());
return power_range_watts_list[pstate].min;
}
double HostEnergy::getWattMaxAt(int pstate)
{
- xbt_assert(not power_range_watts_list.empty(), "No power range properties specified for host %s", host->cname());
+ xbt_assert(not power_range_watts_list.empty(), "No power range properties specified for host %s", host->getCname());
return power_range_watts_list[pstate].max;
}
/** @brief Computes the power consumed by the host according to the current pstate and processor load */
double HostEnergy::getCurrentWattsValue(double cpu_load)
{
- xbt_assert(not power_range_watts_list.empty(), "No power range properties specified for host %s", host->cname());
+ xbt_assert(not power_range_watts_list.empty(), "No power range properties specified for host %s", host->getCname());
/* min_power corresponds to the power consumed when only one core is active */
/* max_power is the power consumed at 100% cpu load */
@@ -276,7 +273,7 @@ double HostEnergy::getCurrentWattsValue(double cpu_load)
* (maxCpuLoad is by definition 1)
*/
double power_slope;
- int coreCount = host->coreCount();
+ int coreCount = host->getCoreCount();
double coreReciprocal = static_cast(1) / static_cast(coreCount);
if (coreCount > 1)
power_slope = (max_power - min_power) / (1 - coreReciprocal);
@@ -304,47 +301,47 @@ double HostEnergy::getConsumedEnergy()
void HostEnergy::initWattsRangeList()
{
- const char* all_power_values_str = host->property("watt_per_state");
+ const char* all_power_values_str = host->getProperty("watt_per_state");
if (all_power_values_str == nullptr)
return;
std::vector all_power_values;
boost::split(all_power_values, all_power_values_str, boost::is_any_of(","));
- XBT_DEBUG("%s: profile: %s, cores: %d", host->cname(), all_power_values_str, host->coreCount());
+ XBT_DEBUG("%s: profile: %s, cores: %d", host->getCname(), all_power_values_str, host->getCoreCount());
int i = 0;
- for (auto current_power_values_str : all_power_values) {
+ for (auto const& current_power_values_str : all_power_values) {
/* retrieve the power values associated with the current pstate */
std::vector current_power_values;
boost::split(current_power_values, current_power_values_str, boost::is_any_of(":"));
- if (host->coreCount() == 1) {
+ if (host->getCoreCount() == 1) {
xbt_assert(current_power_values.size() == 2 || current_power_values.size() == 3,
"Power properties incorrectly defined for host %s."
"It should be 'Idle:FullSpeed' power values because you have one core only.",
- host->cname());
+ host->getCname());
if (current_power_values.size() == 2) {
// 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 formated as 'Idle:FullSpeed' only.\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->cname());
+ host->getCname());
}
} else {
xbt_assert(current_power_values.size() == 3,
"Power properties incorrectly defined for host %s."
"It should be 'Idle:OneCore:AllCores' power values because you have more than one core.",
- host->cname());
+ host->getCname());
}
/* min_power corresponds to the idle power (cpu load = 0) */
/* max_power is the power consumed at 100% cpu load */
- char* msg_idle = bprintf("Invalid idle value for pstate %d on host %s: %%s", i, host->cname());
- char* msg_min = bprintf("Invalid OneCore value for pstate %d on host %s: %%s", i, host->cname());
- char* msg_max = bprintf("Invalid AllCores value for pstate %d on host %s: %%s", i, host->cname());
+ char* msg_idle = bprintf("Invalid idle value for pstate %d on host %s: %%s", i, host->getCname());
+ char* msg_min = bprintf("Invalid OneCore value for pstate %d on host %s: %%s", i, host->getCname());
+ char* msg_max = bprintf("Invalid AllCores value for pstate %d on host %s: %%s", i, host->getCname());
PowerRange range(xbt_str_parse_double((current_power_values.at(0)).c_str(), msg_idle),
xbt_str_parse_double((current_power_values.at(1)).c_str(), msg_min),
xbt_str_parse_double((current_power_values.at(2)).c_str(), msg_max));
@@ -373,7 +370,7 @@ static void onCreation(simgrid::s4u::Host& host)
static void onActionStateChange(simgrid::surf::CpuAction* action, simgrid::surf::Action::State previous)
{
- for (simgrid::surf::Cpu* cpu : action->cpus()) {
+ for (simgrid::surf::Cpu* const& cpu : action->cpus()) {
simgrid::s4u::Host* host = cpu->getHost();
if (host != nullptr) {
@@ -410,7 +407,7 @@ static void onHostDestruction(simgrid::s4u::Host& host)
HostEnergy* host_energy = host.extension();
host_energy->update();
- XBT_INFO("Energy consumption of host %s: %f Joules", host.cname(), host_energy->getConsumedEnergy());
+ XBT_INFO("Energy consumption of host %s: %f Joules", host.getCname(), host_energy->getConsumedEnergy());
}
static void onSimulationEnd()
@@ -466,9 +463,10 @@ void sg_host_energy_update_all()
{
simgrid::simix::kernelImmediate([]() {
std::vector list;
- simgrid::s4u::Engine::instance()->hostList(&list);
- for (auto host : list)
- host->extension()->update();
+ simgrid::s4u::Engine::getInstance()->getHostList(&list);
+ for (auto const& host : list)
+ if (dynamic_cast(host) == nullptr) // Ignore virtual machines
+ host->extension()->update();
});
}
@@ -512,7 +510,7 @@ double sg_host_get_current_consumption(sg_host_t host)
{
xbt_assert(HostEnergy::EXTENSION_ID.valid(),
"The Energy plugin is not active. Please call sg_energy_plugin_init() during initialization.");
- double cpu_load = lmm_constraint_get_usage(host->pimpl_cpu->constraint()) / host->speed();
+ double cpu_load = lmm_constraint_get_usage(host->pimpl_cpu->constraint()) / host->getSpeed();
return host->extension()->getCurrentWattsValue(cpu_load);
}