* 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/s4u/Engine.hpp"
+#include "src/kernel/activity/ExecImpl.hpp"
#include "src/include/surf/surf.hpp"
#include "src/plugins/vm/VirtualMachineImpl.hpp"
#include "src/surf/cpu_interface.hpp"
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_energy, surf, "Logging specific to the SURF energy plugin");
+// Forwards declaration needed to make this function a friend (because friends have external linkage by default)
+static void on_simulation_end();
+
namespace simgrid {
namespace plugin {
};
class HostEnergy {
+ friend void ::on_simulation_end(); // For access to host_was_used_
public:
static simgrid::xbt::Extension<simgrid::s4u::Host, HostEnergy> EXTENSION_ID;
int pstate_ = 0;
const int pstate_off_ = -1;
+ /* Only used to split total energy into unused/used hosts.
+ * If you want to get this info for something else, rather use the host_load plugin
+ */
+ bool host_was_used_ = false;
public:
double watts_off_ = 0.0; /*< Consumption when the machine is turned off (shutdown) */
double total_energy_ = 0.0; /*< Total energy consumed by the host */
if (cpu_load > 1) // A machine with a load > 1 consumes as much as a fully loaded machine, not more
cpu_load = 1;
+ if (cpu_load > 0)
+ host_was_used_ = true;
/* 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
current_power_values.push_back(current_power_values.at(1));
} else { // size == 3
current_power_values[2] = current_power_values.at(1);
- static thread_local bool displayed_warning = false;
+ static 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."
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 = (sg_host_get_computed_flops(hosts[i]) != 0);
double energy = hosts[i]->extension<HostEnergy>()->get_consumed_energy();
total_energy += energy;
- if (host_was_used)
+ if (hosts[i]->extension<HostEnergy>()->host_was_used_)
used_hosts_energy += energy;
}
}
if (HostEnergy::EXTENSION_ID.valid())
return;
- sg_host_load_plugin_init();
-
HostEnergy::EXTENSION_ID = simgrid::s4u::Host::extension_create<HostEnergy>();
simgrid::s4u::Host::on_creation.connect(&on_creation);
simgrid::s4u::Host::on_destruction.connect(&on_host_destruction);
simgrid::s4u::on_simulation_end.connect(&on_simulation_end);
simgrid::surf::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
+ // 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::kernel::activity::ExecImpl::on_creation.connect([](simgrid::kernel::activity::ExecImplPtr activity){
+ if (activity->host_ != nullptr) { // We only run on one host
+ simgrid::s4u::Host* host = activity->host_;
+ if (dynamic_cast<simgrid::s4u::VirtualMachine*>(activity->host_))
+ host = dynamic_cast<simgrid::s4u::VirtualMachine*>(activity->host_)->get_pm();
+
+ host->extension<HostEnergy>()->update();
+ }
+ });
}
/** @ingroup plugin_energy