1 /* Copyright (c) 2010-2019. The SimGrid Team. All rights reserved. */
3 /* This program is free software; you can redistribute it and/or modify it
4 * under the terms of the license (GNU LGPL) which comes with this package. */
6 #include "simgrid/Exception.hpp"
7 #include "simgrid/plugins/energy.h"
8 #include "simgrid/s4u/Engine.hpp"
9 #include "simgrid/s4u/Exec.hpp"
10 #include "src/include/surf/surf.hpp"
11 #include "src/kernel/activity/ExecImpl.hpp"
12 #include "src/plugins/vm/VirtualMachineImpl.hpp"
13 #include "src/surf/cpu_interface.hpp"
15 #include <boost/algorithm/string/classification.hpp>
16 #include <boost/algorithm/string/split.hpp>
18 SIMGRID_REGISTER_PLUGIN(host_energy, "Cpu energy consumption.", &sg_host_energy_plugin_init)
20 /** @defgroup plugin_host_energy
23 This is the energy plugin, enabling to account not only for computation time, but also for the dissipated energy in the
25 To activate this plugin, first call :cpp:func:`sg_host_energy_plugin_init()` before your :cpp:func:`MSG_init()`, and then use
26 :cpp:func:`MSG_host_get_consumed_energy()` to retrieve the consumption of a given host.
28 When the host is on, this energy consumption naturally depends on both the current CPU load and the host energy profile.
29 According to our measurements, the consumption is somehow linear in the amount of cores at full speed, with an
30 abnormality when all the cores are idle. The full details are in `our scientific paper <https://hal.inria.fr/hal-01523608>`_
33 As a result, our energy model takes 4 parameters:
35 - ``Idle`` wattage (i.e., instantaneous consumption in Watt) when your host is up and running, but without anything to do.
36 - ``Epsilon`` wattage when all cores are at 0 or epsilon%, but not in Idle state.
37 - ``AllCores`` wattage when all cores of the host are at 100%.
38 - ``Off`` wattage when the host is turned off.
40 Here is an example of XML declaration:
44 <host id="HostA" speed="100.0Mf" core="4">
45 <prop id="wattage_per_state" value="100.0:120.0:200.0" />
46 <prop id="wattage_off" value="10" />
49 If only two values are given, ``Idle`` is used for the missing ``Epsilon`` value.
51 This example gives the following parameters: ``Off`` is 10 Watts; ``Idle`` is 100 Watts; ``Epsilon`` is 120 Watts and
52 ``AllCores`` is 200 Watts.
53 This is enough to compute the wattage as a function of the amount of loaded cores:
58 <tr><th>#Cores loaded</th><th>Wattage</th><th>Explanation</th></tr>
59 <tr><td>0 (idle)</td><td> 100 Watts </td><td> Idle value</td></tr>
60 <tr><td>0 (not idle)</td><td> 120 Watts</td><td> Epsilon value</td></tr>
61 <tr><td>1</td><td> 140 Watts</td><td> Linear extrapolation between Epsilon and AllCores</td></tr>
62 <tr><td>2</td><td> 160 Watts</td><td> Linear extrapolation between Epsilon and AllCores</td></tr>
63 <tr><td>3</td><td> 180 Watts</td><td> Linear extrapolation between Epsilon and AllCores</td></tr>
64 <tr><td>4</td><td> 200 Watts</td><td> AllCores value</td></tr>
70 <h4>How does DVFS interact with the host energy model?</h4>
72 If your host has several DVFS levels (several pstates), then you should give the energetic profile of each pstate level:
76 <host id="HostC" speed="100.0Mf,50.0Mf,20.0Mf" core="4">
77 <prop id="wattage_per_state"
78 value="95.0:120.0:200.0, 93.0:115.0:170.0, 90.0:110.0:150.0" />
79 <prop id="wattage_off" value="10" />
82 This encodes the following values:
87 <tr><th>pstate</th><th>Performance</th><th>Idle</th><th>Epsilon</th><th>AllCores</th></tr>
88 <tr><td>0</td><td>100 Mflop/s</td><td>95 Watts</td><td>120 Watts</td><td>200 Watts</td></tr>
89 <tr><td>1</td><td>50 Mflop/s</td><td>93 Watts</td><td>115 Watts</td><td>170 Watts</td></tr>
90 <tr><td>2</td><td>20 Mflop/s</td><td>90 Watts</td><td>110 Watts</td><td>150 Watts</td></tr>
93 To change the pstate of a given CPU, use the following functions:
94 :cpp:func:`MSG_host_get_nb_pstates()`, :cpp:func:`simgrid::s4u::Host::set_pstate()`, :cpp:func:`MSG_host_get_power_peak_at()`.
98 <h4>How accurate are these models?</h4>
100 This model cannot be more accurate than your instantiation: with the default values, your result will not be accurate at
101 all. You can still get accurate energy prediction, provided that you carefully instantiate the model.
102 The first step is to ensure that your timing prediction match perfectly. But this is only the first step of the path,
103 and you really want to read `this paper <https://hal.inria.fr/hal-01523608>`_ to see all what you need to do
104 before you can get accurate energy predictions.
109 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_energy, surf, "Logging specific to the SURF energy plugin");
111 // Forwards declaration needed to make this function a friend (because friends have external linkage by default)
112 static void on_simulation_end();
124 PowerRange(double idle, double epsilon, double max) : idle_(idle), epsilon_(epsilon), max_(max), slope_(max-epsilon) {}
128 friend void ::on_simulation_end(); // For access to host_was_used_
130 static simgrid::xbt::Extension<simgrid::s4u::Host, HostEnergy> EXTENSION_ID;
132 explicit HostEnergy(simgrid::s4u::Host* ptr);
135 double get_current_watts_value();
136 double get_current_watts_value(double cpu_load);
137 double get_consumed_energy();
138 double get_watt_idle_at(int pstate);
139 double get_watt_min_at(int pstate);
140 double get_watt_max_at(int pstate);
141 double get_power_range_slope_at(int pstate);
145 void init_watts_range_list();
146 simgrid::s4u::Host* host_ = nullptr;
147 /*< List of (idle_power, epsilon_power, max_power) tuple corresponding to each cpu pstate */
148 std::vector<PowerRange> power_range_watts_list_;
150 /* We need to keep track of what pstate has been used, as we will sometimes be notified only *after* a pstate has been
151 * used (but we need to update the energy consumption with the old pstate!)
154 const int pstate_off_ = -1;
156 /* Only used to split total energy into unused/used hosts.
157 * If you want to get this info for something else, rather use the host_load plugin
159 bool host_was_used_ = false;
161 double watts_off_ = 0.0; /*< Consumption when the machine is turned off (shutdown) */
162 double total_energy_ = 0.0; /*< Total energy consumed by the host */
163 double last_updated_; /*< Timestamp of the last energy update event*/
166 simgrid::xbt::Extension<simgrid::s4u::Host, HostEnergy> HostEnergy::EXTENSION_ID;
168 /* Computes the consumption so far. Called lazily on need. */
169 void HostEnergy::update()
171 double start_time = this->last_updated_;
172 double finish_time = surf_get_clock();
174 // We may have start == finish if the past consumption was updated since the simcall was started
175 // for example if 2 actors requested to update the same host's consumption in a given scheduling round.
177 // Even in this case, we need to save the pstate for the next call (after this if),
178 // which may have changed since that recent update.
179 if (start_time < finish_time) {
180 double previous_energy = this->total_energy_;
182 double instantaneous_power_consumption = this->get_current_watts_value();
184 double energy_this_step = instantaneous_power_consumption * (finish_time - start_time);
186 // TODO Trace: Trace energy_this_step from start_time to finish_time in host->getName()
188 this->total_energy_ = previous_energy + energy_this_step;
189 this->last_updated_ = finish_time;
191 XBT_DEBUG("[update_energy of %s] period=[%.8f-%.8f]; current speed=%.2E flop/s (pstate %i); total consumption "
192 "before: %.8f J -> added now: %.8f J",
193 host_->get_cname(), start_time, finish_time, host_->get_pstate_speed(this->pstate_), this->pstate_,
194 previous_energy, energy_this_step);
197 /* Save data for the upcoming time interval: whether it's on/off and the pstate if it's on */
198 this->pstate_ = host_->is_on() ? host_->get_pstate() : pstate_off_;
201 HostEnergy::HostEnergy(simgrid::s4u::Host* ptr) : host_(ptr), last_updated_(surf_get_clock())
203 init_watts_range_list();
205 const char* off_power_str = host_->get_property("wattage_off");
206 if (off_power_str == nullptr) {
207 off_power_str = host_->get_property("watt_off");
209 static bool warned = false;
210 if (off_power_str != nullptr && not warned) {
212 XBT_WARN("Please use 'wattage_off' instead of 'watt_off' to define the idle wattage of hosts in your XML.");
215 if (off_power_str != nullptr) {
217 this->watts_off_ = std::stod(std::string(off_power_str));
218 } catch (const std::invalid_argument&) {
219 throw std::invalid_argument(std::string("Invalid value for property wattage_off of host ") + host_->get_cname() +
220 ": " + off_power_str);
223 /* watts_off is 0 by default */
226 HostEnergy::~HostEnergy() = default;
228 double HostEnergy::get_watt_idle_at(int pstate)
230 xbt_assert(not power_range_watts_list_.empty(), "No power range properties specified for host %s",
232 return power_range_watts_list_[pstate].idle_;
235 double HostEnergy::get_watt_min_at(int pstate)
237 xbt_assert(not power_range_watts_list_.empty(), "No power range properties specified for host %s",
239 return power_range_watts_list_[pstate].epsilon_;
242 double HostEnergy::get_watt_max_at(int pstate)
244 xbt_assert(not power_range_watts_list_.empty(), "No power range properties specified for host %s",
246 return power_range_watts_list_[pstate].max_;
249 double HostEnergy::get_power_range_slope_at(int pstate)
251 xbt_assert(not power_range_watts_list_.empty(), "No power range properties specified for host %s",
253 return power_range_watts_list_[pstate].slope_;
256 /** @brief Computes the power consumed by the host according to the current situation
258 * - If the host is off, that's the watts_off value
259 * - if it's on, take the current pstate and the current processor load into account */
260 double HostEnergy::get_current_watts_value()
262 if (this->pstate_ == pstate_off_) // The host is off (or was off at the beginning of this time interval)
263 return this->watts_off_;
265 double current_speed = host_->get_pstate_speed(this->pstate_);
269 if (current_speed <= 0)
270 // Some users declare a pstate of speed 0 flops (e.g., to model boot time).
271 // We consider that the machine is then fully loaded. That's arbitrary but it avoids a NaN
274 cpu_load = host_->get_load() / current_speed;
276 /* Divide by the number of cores here to have a value between 0 and 1 */
277 cpu_load /= host_->get_core_count();
279 if (cpu_load > 1) // This condition is true for energy_ptask on 32 bits, even if cpu_load is displayed as 1.000000
280 cpu_load = 1; // That may be an harmless rounding error?
282 host_was_used_ = true;
285 return get_current_watts_value(cpu_load);
288 /** @brief Computes the power that the host would consume at the provided processor load
290 * Whether the host is ON or OFF is not taken into account.
292 double HostEnergy::get_current_watts_value(double cpu_load)
294 xbt_assert(not power_range_watts_list_.empty(), "No power range properties specified for host %s",
297 /* Return watts_off if pstate == pstate_off (ie, if the host is off) */
298 if (this->pstate_ == pstate_off_) {
302 PowerRange power_range = power_range_watts_list_.at(this->pstate_);
303 double current_power;
308 * Something is going on, the host is not idle.
310 * The power consumption follows the regular model:
311 * P(cpu_load) = Pstatic + Pdynamic * cpu_load
312 * where Pstatic = power_range.epsilon_ and Pdynamic = power_range.slope_
313 * and the cpu_load is a value between 0 and 1.
315 current_power = power_range.epsilon_ + cpu_load * power_range.slope_;
319 /* The host is idle, take the dedicated value! */
320 current_power = power_range.idle_;
323 XBT_DEBUG("[get_current_watts] pstate=%i, epsilon_power=%f, max_power=%f, slope=%f", this->pstate_, power_range.epsilon_,
324 power_range.max_, power_range.slope_);
325 XBT_DEBUG("[get_current_watts] Current power (watts) = %f, load = %f", current_power, cpu_load);
327 return current_power;
330 double HostEnergy::get_consumed_energy()
332 if (last_updated_ < surf_get_clock()) // We need to simcall this as it modifies the environment
333 simgrid::kernel::actor::simcall(std::bind(&HostEnergy::update, this));
335 return total_energy_;
338 void HostEnergy::init_watts_range_list()
340 const char* old_prop = host_->get_property("watt_per_state");
341 if (old_prop != nullptr) {
342 std::vector<std::string> all_power_values;
343 boost::split(all_power_values, old_prop, boost::is_any_of(","));
345 xbt_assert(all_power_values.size() == (unsigned)host_->get_pstate_count(),
346 "Invalid XML file. Found %zu energetic profiles for %d pstates", all_power_values.size(),
347 host_->get_pstate_count());
349 // XBT_ATTRIB_DEPRECATED_v328: putting this macro name here so that we find it during the deprecation cleanups
350 std::string msg = std::string("DEPRECATION WARNING: Property 'watt_per_state' will only work until v3.28.\n");
351 msg += std::string("The old syntax 'Idle:OneCore:AllCores' must be converted into 'Idle:Epsilon:AllCores' to "
352 "properly model the consumption of non-whole tasks on mono-core hosts. Here are the values to "
354 host_->get_cname() + "' in your XML file:\n";
355 msg += " <prop id=\"wattage_per_state\" value=\"";
356 for (auto const& current_power_values_str : all_power_values) {
357 std::vector<std::string> current_power_values;
358 boost::split(current_power_values, current_power_values_str, boost::is_any_of(":"));
359 double p_idle = xbt_str_parse_double((current_power_values.at(0)).c_str(),
360 "Invalid obsolete XML file. Fix your watt_per_state property.");
364 if (current_power_values.size() == 3) {
365 double p_one_core = xbt_str_parse_double((current_power_values.at(1)).c_str(),
366 "Invalid obsolete XML file. Fix your watt_per_state property.");
367 p_full = xbt_str_parse_double((current_power_values.at(2)).c_str(),
368 "Invalid obsolete XML file. Fix your watt_per_state property.");
369 if (host_->get_core_count() == 1) {
372 p_epsilon = p_one_core - ((p_full - p_one_core) / (host_->get_core_count() - 1));
374 } else { // consumption given with idle and full only
375 p_full = xbt_str_parse_double((current_power_values.at(1)).c_str(),
376 "Invalid obsolete XML file. Fix your watt_per_state property.");
377 if (host_->get_core_count() == 1) {
384 PowerRange range(p_idle, p_epsilon, p_full);
385 power_range_watts_list_.push_back(range);
387 msg += std::to_string(p_idle) + ":" + std::to_string(p_epsilon) + ":" + std::to_string(p_full);
390 msg.pop_back(); // Remove the extraneous ','
392 XBT_WARN("%s", msg.c_str());
396 const char* all_power_values_str = host_->get_property("wattage_per_state");
397 if (all_power_values_str == nullptr) {
398 /* If no power values are given, we assume it's 0 everywhere */
399 XBT_DEBUG("No energetic profiles given for host %s, using 0 W by default.", host_->get_cname());
400 for (int i = 0; i < host_->get_pstate_count(); ++i) {
401 PowerRange range(0,0,0);
402 power_range_watts_list_.push_back(range);
407 std::vector<std::string> all_power_values;
408 boost::split(all_power_values, all_power_values_str, boost::is_any_of(","));
409 XBT_DEBUG("%s: power properties: %s", host_->get_cname(), all_power_values_str);
411 xbt_assert(all_power_values.size() == (unsigned)host_->get_pstate_count(),
412 "Invalid XML file. Found %zu energetic profiles for %d pstates", all_power_values.size(),
413 host_->get_pstate_count());
416 for (auto const& current_power_values_str : all_power_values) {
417 /* retrieve the power values associated with the pstate i */
418 std::vector<std::string> current_power_values;
419 boost::split(current_power_values, current_power_values_str, boost::is_any_of(":"));
421 xbt_assert(current_power_values.size() == 2 || current_power_values.size() == 3,
422 "Power properties incorrectly defined for host %s."
423 "It should be 'Idle:AllCores' (or 'Idle:Epsilon:AllCores') power values.",
427 double epsilon_power;
430 char* msg_idle = bprintf("Invalid Idle value for pstate %d on host %s: %%s", i, host_->get_cname());
431 char* msg_epsilon = bprintf("Invalid Epsilon value for pstate %d on host %s: %%s", i, host_->get_cname());
432 char* msg_max = bprintf("Invalid AllCores value for pstate %d on host %s: %%s", i, host_->get_cname());
434 idle_power = xbt_str_parse_double((current_power_values.at(0)).c_str(), msg_idle);
435 if (current_power_values.size() == 2) { // Case: Idle:AllCores
436 epsilon_power = xbt_str_parse_double((current_power_values.at(0)).c_str(), msg_idle);
437 max_power = xbt_str_parse_double((current_power_values.at(1)).c_str(), msg_max);
438 } else { // Case: Idle:Epsilon:AllCores
439 epsilon_power = xbt_str_parse_double((current_power_values.at(1)).c_str(), msg_epsilon);
440 max_power = xbt_str_parse_double((current_power_values.at(2)).c_str(), msg_max);
443 XBT_DEBUG("Creating PowerRange for host %s. Idle:%f, Epsilon:%f, AllCores:%f.", host_->get_cname(), idle_power, epsilon_power, max_power);
445 PowerRange range(idle_power, epsilon_power, max_power);
446 power_range_watts_list_.push_back(range);
448 xbt_free(msg_epsilon);
453 } // namespace plugin
454 } // namespace simgrid
456 using simgrid::plugin::HostEnergy;
458 /* **************************** events callback *************************** */
459 static void on_creation(simgrid::s4u::Host& host)
461 if (dynamic_cast<simgrid::s4u::VirtualMachine*>(&host)) // Ignore virtual machines
464 // TODO Trace: set to zero the energy variable associated to host->get_name()
466 host.extension_set(new HostEnergy(&host));
469 static void on_action_state_change(simgrid::kernel::resource::CpuAction const& action,
470 simgrid::kernel::resource::Action::State /*previous*/)
472 for (simgrid::kernel::resource::Cpu* const& cpu : action.cpus()) {
473 simgrid::s4u::Host* host = cpu->get_host();
474 if (host != nullptr) {
476 // If it's a VM, take the corresponding PM
477 simgrid::s4u::VirtualMachine* vm = dynamic_cast<simgrid::s4u::VirtualMachine*>(host);
478 if (vm) // If it's a VM, take the corresponding PM
481 // Get the host_energy extension for the relevant host
482 HostEnergy* host_energy = host->extension<HostEnergy>();
484 if (host_energy->last_updated_ < surf_get_clock())
485 host_energy->update();
490 /* This callback is fired either when the host changes its state (on/off) ("onStateChange") or its speed
491 * (because the user changed the pstate, or because of external trace events) ("onSpeedChange") */
492 static void on_host_change(simgrid::s4u::Host const& host)
494 if (dynamic_cast<simgrid::s4u::VirtualMachine const*>(&host)) // Ignore virtual machines
497 HostEnergy* host_energy = host.extension<HostEnergy>();
499 host_energy->update();
502 static void on_host_destruction(simgrid::s4u::Host const& host)
504 if (dynamic_cast<simgrid::s4u::VirtualMachine const*>(&host)) // Ignore virtual machines
507 XBT_INFO("Energy consumption of host %s: %f Joules", host.get_cname(),
508 host.extension<HostEnergy>()->get_consumed_energy());
511 static void on_simulation_end()
513 std::vector<simgrid::s4u::Host*> hosts = simgrid::s4u::Engine::get_instance()->get_all_hosts();
515 double total_energy = 0.0; // Total energy consumption (whole platform)
516 double used_hosts_energy = 0.0; // Energy consumed by hosts that computed something
517 for (size_t i = 0; i < hosts.size(); i++) {
518 if (dynamic_cast<simgrid::s4u::VirtualMachine*>(hosts[i]) == nullptr) { // Ignore virtual machines
520 double energy = hosts[i]->extension<HostEnergy>()->get_consumed_energy();
521 total_energy += energy;
522 if (hosts[i]->extension<HostEnergy>()->host_was_used_)
523 used_hosts_energy += energy;
526 XBT_INFO("Total energy consumption: %f Joules (used hosts: %f Joules; unused/idle hosts: %f)", total_energy,
527 used_hosts_energy, total_energy - used_hosts_energy);
530 /* **************************** Public interface *************************** */
532 /** @ingroup plugin_host_energy
533 * @brief Enable host energy plugin
534 * @details Enable energy plugin to get joules consumption of each cpu. Call this function before #MSG_init().
536 void sg_host_energy_plugin_init()
538 if (HostEnergy::EXTENSION_ID.valid())
541 HostEnergy::EXTENSION_ID = simgrid::s4u::Host::extension_create<HostEnergy>();
543 simgrid::s4u::Host::on_creation.connect(&on_creation);
544 simgrid::s4u::Host::on_state_change.connect(&on_host_change);
545 simgrid::s4u::Host::on_speed_change.connect(&on_host_change);
546 simgrid::s4u::Host::on_destruction.connect(&on_host_destruction);
547 simgrid::s4u::Engine::on_simulation_end.connect(&on_simulation_end);
548 simgrid::kernel::resource::CpuAction::on_state_change.connect(&on_action_state_change);
549 // We may only have one actor on a node. If that actor executes something like
550 // compute -> recv -> compute
551 // the recv operation will not trigger a "CpuAction::on_state_change". This means
552 // that the next trigger would be the 2nd compute, hence ignoring the idle time
553 // during the recv call. By updating at the beginning of a compute, we can
554 // fix that. (If the cpu is not idle, this is not required.)
555 simgrid::s4u::Exec::on_start.connect([](simgrid::s4u::Actor const&, simgrid::s4u::Exec const& activity) {
556 if (activity.get_host_number() == 1) { // We only run on one host
557 simgrid::s4u::Host* host = activity.get_host();
558 simgrid::s4u::VirtualMachine* vm = dynamic_cast<simgrid::s4u::VirtualMachine*>(host);
561 xbt_assert(host != nullptr);
562 host->extension<HostEnergy>()->update();
567 /** @ingroup plugin_host_energy
568 * @brief updates the consumption of all hosts
570 * After this call, sg_host_get_consumed_energy() will not interrupt your process
571 * (until after the next clock update).
573 void sg_host_energy_update_all()
575 simgrid::kernel::actor::simcall([]() {
576 std::vector<simgrid::s4u::Host*> list = simgrid::s4u::Engine::get_instance()->get_all_hosts();
577 for (auto const& host : list)
578 if (dynamic_cast<simgrid::s4u::VirtualMachine*>(host) == nullptr) { // Ignore virtual machines
579 xbt_assert(host != nullptr);
580 host->extension<HostEnergy>()->update();
585 static void ensure_plugin_inited()
587 if (not HostEnergy::EXTENSION_ID.valid())
588 throw simgrid::xbt::InitializationError("The Energy plugin is not active. Please call sg_host_energy_plugin_init() "
589 "before calling any function related to that plugin.");
592 /** @ingroup plugin_host_energy
593 * @brief Returns the total energy consumed by the host so far (in Joules)
595 * Please note that since the consumption is lazily updated, it may require a simcall to update it.
596 * The result is that the actor requesting this value will be interrupted,
597 * the value will be updated in kernel mode before returning the control to the requesting actor.
599 double sg_host_get_consumed_energy(sg_host_t host)
601 ensure_plugin_inited();
602 return host->extension<HostEnergy>()->get_consumed_energy();
605 /** @ingroup plugin_host_energy
606 * @brief Get the amount of watt dissipated when the host is idling
608 double sg_host_get_idle_consumption(sg_host_t host)
610 ensure_plugin_inited();
611 return host->extension<HostEnergy>()->get_watt_idle_at(0);
614 /** @ingroup plugin_host_energy
615 * @brief Get the amount of watt dissipated at the given pstate when the host is idling
617 double sg_host_get_idle_consumption_at(sg_host_t host, int pstate)
619 ensure_plugin_inited();
620 return host->extension<HostEnergy>()->get_watt_idle_at(pstate);
623 /** @ingroup plugin_host_energy
624 * @brief Get the amount of watt dissipated at the given pstate when the host is at 0 or epsilon% CPU usage.
626 double sg_host_get_wattmin_at(sg_host_t host, int pstate)
628 ensure_plugin_inited();
629 return host->extension<HostEnergy>()->get_watt_min_at(pstate);
631 /** @ingroup plugin_host_energy
632 * @brief Returns the amount of watt dissipated at the given pstate when the host burns CPU at 100%
634 double sg_host_get_wattmax_at(sg_host_t host, int pstate)
636 ensure_plugin_inited();
637 return host->extension<HostEnergy>()->get_watt_max_at(pstate);
639 /** @ingroup plugin_host_energy
640 * @brief Returns the power slope at the given pstate
642 double sg_host_get_power_range_slope_at(sg_host_t host, int pstate)
644 ensure_plugin_inited();
645 return host->extension<HostEnergy>()->get_power_range_slope_at(pstate);
647 /** @ingroup plugin_host_energy
648 * @brief Returns the current consumption of the host
650 double sg_host_get_current_consumption(sg_host_t host)
652 ensure_plugin_inited();
653 return host->extension<HostEnergy>()->get_current_watts_value();