* under the terms of the license (GNU LGPL) which comes with this package. */
#include "simgrid/plugins/energy.h"
+#include "simgrid/plugins/load.h"
#include "simgrid/simix.hpp"
#include "src/plugins/vm/VirtualMachineImpl.hpp"
#include "src/surf/cpu_interface.hpp"
### 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}
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_energy, surf, "Logging specific to the SURF energy plugin");
namespace simgrid {
-namespace energy {
+namespace plugin {
class PowerRange {
public:
explicit HostEnergy(simgrid::s4u::Host* ptr);
~HostEnergy();
+ double getCurrentWattsValue();
double getCurrentWattsValue(double cpu_load);
double getConsumedEnergy();
double getWattMinAt(int pstate);
{
double start_time = this->last_updated;
double finish_time = surf_get_clock();
- double current_speed = host->getSpeed();
if (start_time < finish_time) {
- 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).
- // We consider that the machine is then fully loaded. That's arbitrary but it avoids a NaN
- cpu_load = 1;
- else
- cpu_load = lmm_constraint_get_usage(host->pimpl_cpu->constraint()) / current_speed;
-
- /** Divide by the number of cores here **/
- cpu_load /= host->pimpl_cpu->coreCount();
-
- if (cpu_load > 1) // A machine with a load > 1 consumes as much as a fully loaded machine, not more
- cpu_load = 1;
-
- /* The problem with this model is that the load is always 0 or 1, never something less.
- * Another possibility could be to model the total energy as
- *
- * X/(X+Y)*W_idle + Y/(X+Y)*W_burn
- *
- * where X is the amount of idling cores, and Y the amount of computing cores.
- */
-
double previous_energy = this->total_energy;
- double instantaneous_consumption;
- 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);
+ double instantaneous_consumption = this->getCurrentWattsValue();
double energy_this_step = instantaneous_consumption * (finish_time - start_time);
- // TODO Trace: Trace energy_this_step from start_time to finish_time in host->name()
+ // TODO Trace: Trace energy_this_step from start_time to finish_time in host->getName()
this->total_energy = previous_energy + energy_this_step;
this->last_updated = finish_time;
return power_range_watts_list[pstate].max;
}
-/** @brief Computes the power consumed by the host according to the current pstate and processor load */
+/** @brief Computes the power consumed by the host according to the current situation
+ *
+ * - If the host is off, that's the watts_off value
+ * - if it's on, take the current pstate and the current processor load into account */
+double HostEnergy::getCurrentWattsValue()
+{
+ if (this->pstate == pstate_off) // The host is off (or was off at the beginning of this time interval)
+ return this->watts_off;
+
+ double current_speed = host->getSpeed();
+
+ 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).
+ // We consider that the machine is then fully loaded. That's arbitrary but it avoids a NaN
+ cpu_load = 1;
+ else
+ cpu_load = host->pimpl_cpu->constraint()->get_usage() / current_speed;
+
+ /** Divide by the number of cores here **/
+ cpu_load /= host->pimpl_cpu->coreCount();
+
+ if (cpu_load > 1) // A machine with a load > 1 consumes as much as a fully loaded machine, not more
+ cpu_load = 1;
+
+ /* The problem with this model is that the load is always 0 or 1, never something less.
+ * Another possibility could be to model the total energy as
+ *
+ * X/(X+Y)*W_idle + Y/(X+Y)*W_burn
+ *
+ * where X is the amount of idling cores, and Y the amount of computing cores.
+ */
+ return getCurrentWattsValue(cpu_load);
+}
+
+/** @brief Computes the power that the host would consume at the provided processor load
+ *
+ * Whether the host is ON or OFF is not taken into account.
+ */
double HostEnergy::getCurrentWattsValue(double cpu_load)
{
xbt_assert(not power_range_watts_list.empty(), "No power range properties specified for host %s", host->getCname());
+ /*
+ * * Return watts_off if pstate == pstate_off
+ * * this happens when host is off
+ */
+ if (this->pstate == pstate_off) {
+ return watts_off;
+ }
+
/* min_power corresponds to the power consumed when only one core is active */
/* max_power is the power consumed at 100% cpu load */
auto range = power_range_watts_list.at(this->pstate);
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<std::string> current_power_values;
boost::split(current_power_values, current_power_values_str, boost::is_any_of(":"));
} 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->getCname());
}
}
-using simgrid::energy::HostEnergy;
+using simgrid::plugin::HostEnergy;
/* **************************** events callback *************************** */
static void onCreation(simgrid::s4u::Host& host)
if (dynamic_cast<simgrid::s4u::VirtualMachine*>(&host)) // Ignore virtual machines
return;
- //TODO Trace: set to zero the energy variable associated to host->name()
+ // TODO Trace: set to zero the energy variable associated to host->getName()
host.extension_set(new HostEnergy(&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) {
// If it's a VM, take the corresponding PM
simgrid::s4u::VirtualMachine* vm = dynamic_cast<simgrid::s4u::VirtualMachine*>(host);
if (vm) // If it's a VM, take the corresponding PM
- host = vm->pimpl_vm_->getPm();
+ host = vm->getPm();
// Get the host_energy extension for the relevant host
HostEnergy* host_energy = host->extension<HostEnergy>();
if (dynamic_cast<simgrid::s4u::VirtualMachine*>(&host)) // Ignore virtual machines
return;
- HostEnergy* host_energy = host.extension<HostEnergy>();
- host_energy->update();
- XBT_INFO("Energy consumption of host %s: %f Joules", host.getCname(), host_energy->getConsumedEnergy());
+ XBT_INFO("Energy consumption of host %s: %f Joules", host.getCname(),
+ host.extension<HostEnergy>()->getConsumedEnergy());
}
static void onSimulationEnd()
{
- sg_host_t* host_list = sg_host_list();
- int host_count = sg_host_count();
+ std::vector<simgrid::s4u::Host*> hosts = simgrid::s4u::Engine::getInstance()->getAllHosts();
+
double total_energy = 0.0; // Total energy consumption (whole platform)
double used_hosts_energy = 0.0; // Energy consumed by hosts that computed something
- for (int i = 0; i < host_count; i++) {
- if (dynamic_cast<simgrid::s4u::VirtualMachine*>(host_list[i]) == nullptr) { // Ignore virtual machines
+ for (size_t i = 0; i < hosts.size(); i++) {
+ if (dynamic_cast<simgrid::s4u::VirtualMachine*>(hosts[i]) == nullptr) { // Ignore virtual machines
- bool host_was_used = (host_list[i]->extension<HostEnergy>()->last_updated != 0);
- double energy = host_list[i]->extension<HostEnergy>()->getConsumedEnergy();
+ bool host_was_used = (sg_host_get_computed_flops(hosts[i]) != 0);
+ double energy = hosts[i]->extension<HostEnergy>()->getConsumedEnergy();
total_energy += energy;
if (host_was_used)
used_hosts_energy += energy;
}
XBT_INFO("Total energy consumption: %f Joules (used hosts: %f Joules; unused/idle hosts: %f)",
total_energy, used_hosts_energy, total_energy - used_hosts_energy);
- xbt_free(host_list);
}
/* **************************** Public interface *************************** */
-SG_BEGIN_DECL()
+extern "C" {
/** \ingroup plugin_energy
* \brief Enable host energy plugin
if (HostEnergy::EXTENSION_ID.valid())
return;
+ sg_host_load_plugin_init();
+
HostEnergy::EXTENSION_ID = simgrid::s4u::Host::extension_create<HostEnergy>();
simgrid::s4u::Host::onCreation.connect(&onCreation);
void sg_host_energy_update_all()
{
simgrid::simix::kernelImmediate([]() {
- std::vector<simgrid::s4u::Host*> list;
- simgrid::s4u::Engine::getInstance()->getHostList(&list);
- for (auto host : list)
+ std::vector<simgrid::s4u::Host*> list = simgrid::s4u::Engine::getInstance()->getAllHosts();
+ for (auto const& host : list)
if (dynamic_cast<simgrid::s4u::VirtualMachine*>(host) == nullptr) // Ignore virtual machines
host->extension<HostEnergy>()->update();
});
{
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->getSpeed();
- return host->extension<HostEnergy>()->getCurrentWattsValue(cpu_load);
+ return host->extension<HostEnergy>()->getCurrentWattsValue();
+}
}
-
-SG_END_DECL()