Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
New doc section on plugins
[simgrid.git] / src / plugins / host_energy.cpp
1 /* Copyright (c) 2010-2019. The SimGrid Team. All rights reserved.          */
2
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. */
5
6 #include "simgrid/plugins/energy.h"
7 #include "simgrid/s4u/Engine.hpp"
8 #include "src/kernel/activity/ExecImpl.hpp"
9 #include "src/include/surf/surf.hpp"
10 #include "src/plugins/vm/VirtualMachineImpl.hpp"
11 #include "src/surf/cpu_interface.hpp"
12
13 #include <boost/algorithm/string/classification.hpp>
14 #include <boost/algorithm/string/split.hpp>
15
16 SIMGRID_REGISTER_PLUGIN(host_energy, "Cpu energy consumption.", &sg_host_energy_plugin_init)
17
18 /** @defgroup plugin_host_energy
19
20 This is the energy plugin, enabling to account not only for computation time, but also for the dissipated energy in the
21 simulated platform.
22 To activate this plugin, first call sg_host_energy_plugin_init() before your #MSG_init(), and then use
23 MSG_host_get_consumed_energy() to retrieve the consumption of a given host.
24
25 When the host is on, this energy consumption naturally depends on both the current CPU load and the host energy profile.
26 According to our measurements, the consumption is somehow linear in the amount of cores at full speed, with an
27 abnormality when all the cores are idle. The full details are in
28 <a href="https://hal.inria.fr/hal-01523608">our scientific paper</a> on that topic.
29
30 As a result, our energy model takes 4 parameters:
31
32   - @b Idle: wattage (i.e., instantaneous consumption in Watt) when your host is up and running, but without anything to
33 do.
34   - @b Epsilon: wattage when all cores are at 0 or epsilon%, but not in Idle state.
35   - @b AllCores: wattage when all cores of the host are at 100%.
36   - @b Off: wattage when the host is turned off.
37
38 Here is an example of XML declaration:
39
40 @code{.xml}
41 <host id="HostA" speed="100.0Mf" core="4">
42     <prop id="wattage_per_state" value="100.0:120.0:200.0" />
43     <prop id="wattage_off" value="10" />
44 </host>
45 @endcode
46
47 If the 'Epsilon' parameter is omitted in the XML declaration, 'Idle' is used instead.
48
49 This example gives the following parameters: @b Off is 10 Watts; @b Idle is 100 Watts; @b Epsilon is 120 Watts and @b
50 AllCores is 200 Watts.
51 This is enough to compute the wattage as a function of the amount of loaded cores:
52
53 <table>
54 <tr><th>@#Cores loaded</th><th>Wattage</th><th>Explanation</th></tr>
55 <tr><td>0 (idle)</td><td> 100 Watts</td><td>Idle value</td></tr>
56 <tr><td>0 (not idle)</td><td> 120 Watts</td><td>Epsilon value</td></tr>
57 <tr><td>1</td><td> 140 Watts</td><td>linear extrapolation between Epsilon and AllCores</td></tr>
58 <tr><td>2</td><td> 160 Watts</td><td>linear extrapolation between Epsilon and AllCores</td></tr>
59 <tr><td>3</td><td> 180 Watts</td><td>linear extrapolation between Epsilon and AllCores</td></tr>
60 <tr><td>4</td><td> 200 Watts</td><td>AllCores value</td></tr>
61 </table>
62
63
64 ### How does DVFS interact with the host energy model?
65
66 If your host has several DVFS levels (several pstates), then you should give the energetic profile of each pstate level:
67
68 @code{.xml}
69 <host id="HostC" speed="100.0Mf,50.0Mf,20.0Mf" core="4">
70     <prop id="wattage_per_state" value="95.0:120.0:200.0, 93.0:115.0:170.0, 90.0:110.0:150.0" />
71     <prop id="wattage_off" value="10" />
72 </host>
73 @endcode
74
75 This encodes the following values
76 <table>
77 <tr><th>pstate</th><th>Performance</th><th>Idle</th><th>Epsilon</th><th>AllCores</th></tr>
78 <tr><td>0</td><td>100 Mflop/s</td><td>95 Watts</td><td>120 Watts</td><td>200 Watts</td></tr>
79 <tr><td>1</td><td>50 Mflop/s</td><td>93 Watts</td><td>115 Watts</td><td>170 Watts</td></tr>
80 <tr><td>2</td><td>20 Mflop/s</td><td>90 Watts</td><td>110 Watts</td><td>150 Watts</td></tr>
81 </table>
82
83 To change the pstate of a given CPU, use the following functions:
84 #MSG_host_get_nb_pstates(), simgrid#s4u#Host#setPstate(), #MSG_host_get_power_peak_at().
85
86 ### How accurate are these models?
87
88 This model cannot be more accurate than your instantiation: with the default values, your result will not be accurate at
89 all. You can still get accurate energy prediction, provided that you carefully instantiate the model.
90 The first step is to ensure that your timing prediction match perfectly. But this is only the first step of the path,
91 and you really want to read <a href="https://hal.inria.fr/hal-01523608">this paper</a> to see all what you need to do
92 before you can get accurate energy predictions.
93  */
94
95 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_energy, surf, "Logging specific to the SURF energy plugin");
96
97 // Forwards declaration needed to make this function a friend (because friends have external linkage by default)
98 static void on_simulation_end();
99
100 namespace simgrid {
101 namespace plugin {
102
103 class PowerRange {
104 public:
105   double idle_;
106   double epsilon_;
107   double max_;
108   double slope_;
109
110   PowerRange(double idle, double epsilon, double max) : idle_(idle), epsilon_(epsilon), max_(max), slope_(max-epsilon) {}
111 };
112
113 class HostEnergy {
114   friend void ::on_simulation_end(); // For access to host_was_used_
115 public:
116   static simgrid::xbt::Extension<simgrid::s4u::Host, HostEnergy> EXTENSION_ID;
117
118   explicit HostEnergy(simgrid::s4u::Host* ptr);
119   ~HostEnergy();
120
121   double get_current_watts_value();
122   double get_current_watts_value(double cpu_load);
123   double get_consumed_energy();
124   double get_idle_consumption();
125   double get_watt_min_at(int pstate);
126   double get_watt_max_at(int pstate);
127   double get_power_range_slope_at(int pstate);
128   void update();
129
130 private:
131   void init_watts_range_list();
132   simgrid::s4u::Host* host_ = nullptr;
133   /*< List of (idle_power, epsilon_power, max_power) tuple corresponding to each cpu pstate */
134   std::vector<PowerRange> power_range_watts_list_;
135
136   /* We need to keep track of what pstate has been used, as we will sometimes be notified only *after* a pstate has been
137    * used (but we need to update the energy consumption with the old pstate!)
138    */
139   int pstate_           = 0;
140   const int pstate_off_ = -1;
141
142   /* Only used to split total energy into unused/used hosts.
143    * If you want to get this info for something else, rather use the host_load plugin
144    */
145   bool host_was_used_  = false;
146 public:
147   double watts_off_    = 0.0; /*< Consumption when the machine is turned off (shutdown) */
148   double total_energy_ = 0.0; /*< Total energy consumed by the host */
149   double last_updated_;       /*< Timestamp of the last energy update event*/
150 };
151
152 simgrid::xbt::Extension<simgrid::s4u::Host, HostEnergy> HostEnergy::EXTENSION_ID;
153
154 /* Computes the consumption so far. Called lazily on need. */
155 void HostEnergy::update()
156 {
157   double start_time  = this->last_updated_;
158   double finish_time = surf_get_clock();
159   //
160   // We may have start == finish if the past consumption was updated since the simcall was started
161   // for example if 2 actors requested to update the same host's consumption in a given scheduling round.
162   //
163   // Even in this case, we need to save the pstate for the next call (after this if),
164   // which may have changed since that recent update.
165   if (start_time < finish_time) {
166     double previous_energy = this->total_energy_;
167
168     double instantaneous_power_consumption = this->get_current_watts_value();
169
170     double energy_this_step = instantaneous_power_consumption * (finish_time - start_time);
171
172     // TODO Trace: Trace energy_this_step from start_time to finish_time in host->getName()
173
174     this->total_energy_ = previous_energy + energy_this_step;
175     this->last_updated_ = finish_time;
176
177     XBT_DEBUG("[update_energy of %s] period=[%.8f-%.8f]; current speed=%.2E flop/s (pstate %i); total consumption before: %.8f J -> added now: %.8f J",
178               host_->get_cname(), start_time, finish_time, host_->pimpl_cpu->get_pstate_peak_speed(this->pstate_), this->pstate_, previous_energy,
179               energy_this_step);
180   }
181
182   /* Save data for the upcoming time interval: whether it's on/off and the pstate if it's on */
183   this->pstate_ = host_->is_on() ? host_->get_pstate() : pstate_off_;
184 }
185
186 HostEnergy::HostEnergy(simgrid::s4u::Host* ptr) : host_(ptr), last_updated_(surf_get_clock())
187 {
188   init_watts_range_list();
189   static bool warned = false;
190
191   const char* off_power_str = host_->get_property("wattage_off");
192   if (off_power_str == nullptr) {
193     off_power_str = host_->get_property("watt_off");
194     if (off_power_str != nullptr && not warned) {
195       warned = true;
196       XBT_WARN("Please use 'wattage_off' instead of 'watt_off' to define the idle wattage of hosts in your XML.");
197     }
198   }
199   if (off_power_str != nullptr) {
200     try {
201       this->watts_off_ = std::stod(std::string(off_power_str));
202     } catch (const std::invalid_argument&) {
203       throw std::invalid_argument(std::string("Invalid value for property wattage_off of host ") + host_->get_cname() +
204                                   ": " + off_power_str);
205     }
206   }
207   /* watts_off is 0 by default */
208 }
209
210 HostEnergy::~HostEnergy() = default;
211
212 double HostEnergy::get_idle_consumption()
213 {
214   xbt_assert(not power_range_watts_list_.empty(), "No power range properties specified for host %s",
215              host_->get_cname());
216
217   return power_range_watts_list_[0].idle_;
218 }
219
220 double HostEnergy::get_watt_min_at(int pstate)
221 {
222   xbt_assert(not power_range_watts_list_.empty(), "No power range properties specified for host %s",
223              host_->get_cname());
224   return power_range_watts_list_[pstate].epsilon_;
225 }
226
227 double HostEnergy::get_watt_max_at(int pstate)
228 {
229   xbt_assert(not power_range_watts_list_.empty(), "No power range properties specified for host %s",
230              host_->get_cname());
231   return power_range_watts_list_[pstate].max_;
232 }
233
234 double HostEnergy::get_power_range_slope_at(int pstate)
235 {
236     xbt_assert(not power_range_watts_list_.empty(), "No power range properties specified for host %s",
237                host_->get_cname());
238    return power_range_watts_list_[pstate].slope_;
239 }
240
241 /** @brief Computes the power consumed by the host according to the current situation
242  *
243  * - If the host is off, that's the watts_off value
244  * - if it's on, take the current pstate and the current processor load into account */
245 double HostEnergy::get_current_watts_value()
246 {
247   if (this->pstate_ == pstate_off_) // The host is off (or was off at the beginning of this time interval)
248     return this->watts_off_;
249
250   double current_speed = host_->get_pstate_speed(this->pstate_);
251
252   double cpu_load;
253
254   if (current_speed <= 0)
255     // Some users declare a pstate of speed 0 flops (e.g., to model boot time).
256     // We consider that the machine is then fully loaded. That's arbitrary but it avoids a NaN
257     cpu_load = 1;
258   else {
259     cpu_load = host_->pimpl_cpu->get_constraint()->get_usage() / current_speed;
260
261     /* Divide by the number of cores here to have a value between 0 and 1 */
262     cpu_load /= host_->pimpl_cpu->get_core_count();
263
264     if (cpu_load > 1) // A machine with a load > 1 consumes as much as a fully loaded machine, not more
265       cpu_load = 1;
266     if (cpu_load > 0)
267       host_was_used_ = true;
268   }
269
270   return get_current_watts_value(cpu_load);
271 }
272
273 /** @brief Computes the power that the host would consume at the provided processor load
274  *
275  * Whether the host is ON or OFF is not taken into account.
276  */
277 double HostEnergy::get_current_watts_value(double cpu_load)
278 {
279   xbt_assert(not power_range_watts_list_.empty(), "No power range properties specified for host %s",
280              host_->get_cname());
281
282   /* Return watts_off if pstate == pstate_off (ie, if the host is off) */
283   if (this->pstate_ == pstate_off_) {
284     return watts_off_;
285   }
286
287   PowerRange power_range = power_range_watts_list_.at(this->pstate_);
288   double current_power;
289
290   if (cpu_load > 0)
291   {
292       /**
293        * Something is going on, the host is not idle.
294        *
295        * The power consumption follows the regular model:
296        * P(cpu_load) = Pstatic + Pdynamic * cpu_load
297        * where Pstatic = power_range.epsilon_ and Pdynamic = power_range.slope_
298        * and the cpu_load is a value between 0 and 1.
299        */
300       current_power = power_range.epsilon_ + cpu_load * power_range.slope_;
301   }
302   else
303   {
304       /* The host is idle, take the dedicated value! */
305       current_power = power_range.idle_;
306   }
307
308   XBT_DEBUG("[get_current_watts] pstate=%i, epsilon_power=%f, max_power=%f, slope=%f", this->pstate_, power_range.epsilon_,
309             power_range.max_, power_range.slope_);
310   XBT_DEBUG("[get_current_watts] Current power (watts) = %f, load = %f", current_power, cpu_load);
311
312   return current_power;
313 }
314
315 double HostEnergy::get_consumed_energy()
316 {
317   if (last_updated_ < surf_get_clock()) // We need to simcall this as it modifies the environment
318     simgrid::kernel::actor::simcall(std::bind(&HostEnergy::update, this));
319
320   return total_energy_;
321 }
322
323 void HostEnergy::init_watts_range_list()
324 {
325   const char* old_prop = host_->get_property("watt_per_state");
326   if (old_prop != nullptr) {
327     std::vector<std::string> all_power_values;
328     boost::split(all_power_values, old_prop, boost::is_any_of(","));
329
330     std::string msg = std::string("DEPRECATION WARNING: Property 'watt_per_state' will not work after v3.28.\n");
331     msg += std::string("The old syntax 'Idle:OneCore:AllCores' must be converted into 'Idle:Epsilon:AllCores' to "
332                        "properly model the consumption of non-whole tasks on mono-core hosts. Here are the values to "
333                        "use for host '") +
334            host_->get_cname() + "' in your XML file:\n";
335     msg += "     <prop id=\"wattage_per_state\" value=\"";
336     for (auto const& current_power_values_str : all_power_values) {
337       std::vector<std::string> current_power_values;
338       boost::split(current_power_values, current_power_values_str, boost::is_any_of(":"));
339       double p_idle = xbt_str_parse_double((current_power_values.at(0)).c_str(),
340                                            "Invalid obsolete XML file. Fix your watt_per_state property.");
341       double p_one_core;
342       double p_full;
343       double p_epsilon;
344
345       if (current_power_values.size() == 2) { // Case: Idle:AllCores
346         p_full    = xbt_str_parse_double((current_power_values.at(1)).c_str(),
347                                       "Invalid obsolete XML file. Fix your watt_per_state property.");
348         p_epsilon = p_full;
349       } else { // Case: Idle:Epsilon:AllCores
350         p_one_core = xbt_str_parse_double((current_power_values.at(1)).c_str(),
351                                           "Invalid obsolete XML file. Fix your watt_per_state property.");
352         p_full     = xbt_str_parse_double((current_power_values.at(2)).c_str(),
353                                       "Invalid obsolete XML file. Fix your watt_per_state property.");
354         if (host_->get_core_count() == 1)
355           p_epsilon = p_full;
356         else
357           p_epsilon = p_one_core - ((p_full - p_one_core) / (host_->get_core_count() - 1));
358       }
359       PowerRange range(p_idle, p_epsilon, p_full);
360       power_range_watts_list_.push_back(range);
361
362       msg += std::to_string(p_idle) + ":" + std::to_string(p_epsilon) + ":" + std::to_string(p_full);
363       msg += ",";
364     }
365     msg.pop_back(); // Remove the extraneous ','
366     msg += "\" />";
367     XBT_WARN("%s", msg.c_str());
368     return;
369   }
370   const char* all_power_values_str = host_->get_property("wattage_per_state");
371   if (all_power_values_str == nullptr)
372     return;
373
374   std::vector<std::string> all_power_values;
375   boost::split(all_power_values, all_power_values_str, boost::is_any_of(","));
376   XBT_DEBUG("%s: power properties: %s", host_->get_cname(), all_power_values_str);
377
378   int i = 0;
379   for (auto const& current_power_values_str : all_power_values) {
380     /* retrieve the power values associated with the pstate i */
381     std::vector<std::string> current_power_values;
382     boost::split(current_power_values, current_power_values_str, boost::is_any_of(":"));
383
384     xbt_assert(current_power_values.size() == 2 || current_power_values.size() == 3,
385                "Power properties incorrectly defined for host %s."
386                "It should be 'Idle:AllCores' (or 'Idle:Epsilon:AllCores') power values.",
387                host_->get_cname());
388
389     double idle_power;
390     double epsilon_power;
391     double max_power;
392
393     char* msg_idle    = bprintf("Invalid Idle value for pstate %d on host %s: %%s", i, host_->get_cname());
394     char* msg_epsilon = bprintf("Invalid Epsilon value for pstate %d on host %s: %%s", i, host_->get_cname());
395     char* msg_max     = bprintf("Invalid AllCores value for pstate %d on host %s: %%s", i, host_->get_cname());
396
397     idle_power = xbt_str_parse_double((current_power_values.at(0)).c_str(), msg_idle);
398     if (current_power_values.size() == 2) { // Case: Idle:AllCores
399       epsilon_power = xbt_str_parse_double((current_power_values.at(0)).c_str(), msg_idle);
400       max_power     = xbt_str_parse_double((current_power_values.at(1)).c_str(), msg_max);
401     } else { // Case: Idle:Epsilon:AllCores
402       epsilon_power = xbt_str_parse_double((current_power_values.at(1)).c_str(), msg_epsilon);
403       max_power     = xbt_str_parse_double((current_power_values.at(2)).c_str(), msg_max);
404     }
405
406     XBT_DEBUG("Creating PowerRange for host %s. Idle:%f, Epsilon:%f, AllCores:%f.", host_->get_cname(), idle_power, epsilon_power, max_power);
407
408     PowerRange range(idle_power, epsilon_power, max_power);
409     power_range_watts_list_.push_back(range);
410     xbt_free(msg_idle);
411     xbt_free(msg_epsilon);
412     xbt_free(msg_max);
413     ++i;
414   }
415 }
416 } // namespace plugin
417 } // namespace simgrid
418
419 using simgrid::plugin::HostEnergy;
420
421 /* **************************** events  callback *************************** */
422 static void on_creation(simgrid::s4u::Host& host)
423 {
424   if (dynamic_cast<simgrid::s4u::VirtualMachine*>(&host)) // Ignore virtual machines
425     return;
426
427   // TODO Trace: set to zero the energy variable associated to host->getName()
428
429   host.extension_set(new HostEnergy(&host));
430 }
431
432 static void on_action_state_change(simgrid::kernel::resource::CpuAction const& action,
433                                    simgrid::kernel::resource::Action::State /*previous*/)
434 {
435   for (simgrid::kernel::resource::Cpu* const& cpu : action.cpus()) {
436     simgrid::s4u::Host* host = cpu->get_host();
437     if (host != nullptr) {
438
439       // If it's a VM, take the corresponding PM
440       simgrid::s4u::VirtualMachine* vm = dynamic_cast<simgrid::s4u::VirtualMachine*>(host);
441       if (vm) // If it's a VM, take the corresponding PM
442         host = vm->get_pm();
443
444       // Get the host_energy extension for the relevant host
445       HostEnergy* host_energy = host->extension<HostEnergy>();
446
447       if (host_energy->last_updated_ < surf_get_clock())
448         host_energy->update();
449     }
450   }
451 }
452
453 /* This callback is fired either when the host changes its state (on/off) ("onStateChange") or its speed
454  * (because the user changed the pstate, or because of external trace events) ("onSpeedChange") */
455 static void on_host_change(simgrid::s4u::Host const& host)
456 {
457   if (dynamic_cast<simgrid::s4u::VirtualMachine const*>(&host)) // Ignore virtual machines
458     return;
459
460   HostEnergy* host_energy = host.extension<HostEnergy>();
461
462   host_energy->update();
463 }
464
465 static void on_host_destruction(simgrid::s4u::Host const& host)
466 {
467   if (dynamic_cast<simgrid::s4u::VirtualMachine const*>(&host)) // Ignore virtual machines
468     return;
469
470   XBT_INFO("Energy consumption of host %s: %f Joules", host.get_cname(),
471            host.extension<HostEnergy>()->get_consumed_energy());
472 }
473
474 static void on_simulation_end()
475 {
476   std::vector<simgrid::s4u::Host*> hosts = simgrid::s4u::Engine::get_instance()->get_all_hosts();
477
478   double total_energy      = 0.0; // Total energy consumption (whole platform)
479   double used_hosts_energy = 0.0; // Energy consumed by hosts that computed something
480   for (size_t i = 0; i < hosts.size(); i++) {
481     if (dynamic_cast<simgrid::s4u::VirtualMachine*>(hosts[i]) == nullptr) { // Ignore virtual machines
482
483       double energy      = hosts[i]->extension<HostEnergy>()->get_consumed_energy();
484       total_energy += energy;
485       if (hosts[i]->extension<HostEnergy>()->host_was_used_)
486         used_hosts_energy += energy;
487     }
488   }
489   XBT_INFO("Total energy consumption: %f Joules (used hosts: %f Joules; unused/idle hosts: %f)", total_energy,
490            used_hosts_energy, total_energy - used_hosts_energy);
491 }
492
493 /* **************************** Public interface *************************** */
494
495 /** @ingroup plugin_host_energy
496  * @brief Enable host energy plugin
497  * @details Enable energy plugin to get joules consumption of each cpu. Call this function before #MSG_init().
498  */
499 void sg_host_energy_plugin_init()
500 {
501   if (HostEnergy::EXTENSION_ID.valid())
502     return;
503
504   HostEnergy::EXTENSION_ID = simgrid::s4u::Host::extension_create<HostEnergy>();
505
506   simgrid::s4u::Host::on_creation.connect(&on_creation);
507   simgrid::s4u::Host::on_state_change.connect(&on_host_change);
508   simgrid::s4u::Host::on_speed_change.connect(&on_host_change);
509   simgrid::s4u::Host::on_destruction.connect(&on_host_destruction);
510   simgrid::s4u::Engine::on_simulation_end.connect(&on_simulation_end);
511   simgrid::kernel::resource::CpuAction::on_state_change.connect(&on_action_state_change);
512   // We may only have one actor on a node. If that actor executes something like
513   //   compute -> recv -> compute
514   // the recv operation will not trigger a "CpuAction::on_state_change". This means
515   // that the next trigger would be the 2nd compute, hence ignoring the idle time
516   // during the recv call. By updating at the beginning of a compute, we can
517   // fix that. (If the cpu is not idle, this is not required.)
518   simgrid::kernel::activity::ExecImpl::on_creation.connect([](simgrid::kernel::activity::ExecImpl const& activity) {
519     if (activity.get_host_number() == 1) { // We only run on one host
520       simgrid::s4u::Host* host         = activity.get_host();
521       simgrid::s4u::VirtualMachine* vm = dynamic_cast<simgrid::s4u::VirtualMachine*>(host);
522       if (vm != nullptr)
523         host = vm->get_pm();
524       xbt_assert(host != nullptr);
525       host->extension<HostEnergy>()->update();
526     }
527   });
528 }
529
530 /** @ingroup plugin_host_energy
531  *  @brief updates the consumption of all hosts
532  *
533  * After this call, sg_host_get_consumed_energy() will not interrupt your process
534  * (until after the next clock update).
535  */
536 void sg_host_energy_update_all()
537 {
538   simgrid::kernel::actor::simcall([]() {
539     std::vector<simgrid::s4u::Host*> list = simgrid::s4u::Engine::get_instance()->get_all_hosts();
540     for (auto const& host : list)
541       if (dynamic_cast<simgrid::s4u::VirtualMachine*>(host) == nullptr) { // Ignore virtual machines
542         xbt_assert(host != nullptr);
543         host->extension<HostEnergy>()->update();
544       }
545   });
546 }
547
548 /** @ingroup plugin_host_energy
549  *  @brief Returns the total energy consumed by the host so far (in Joules)
550  *
551  *  Please note that since the consumption is lazily updated, it may require a simcall to update it.
552  *  The result is that the actor requesting this value will be interrupted,
553  *  the value will be updated in kernel mode before returning the control to the requesting actor.
554  */
555 double sg_host_get_consumed_energy(sg_host_t host)
556 {
557   xbt_assert(HostEnergy::EXTENSION_ID.valid(),
558              "The Energy plugin is not active. Please call sg_host_energy_plugin_init() during initialization.");
559   return host->extension<HostEnergy>()->get_consumed_energy();
560 }
561
562 /** @ingroup plugin_host_energy
563  *  @brief Get the amount of watt dissipated when the host is idling
564  */
565 double sg_host_get_idle_consumption(sg_host_t host)
566 {
567   xbt_assert(HostEnergy::EXTENSION_ID.valid(),
568              "The Energy plugin is not active. Please call sg_host_energy_plugin_init() during initialization.");
569   return host->extension<HostEnergy>()->get_idle_consumption();
570 }
571
572 /** @ingroup plugin_host_energy
573  *  @brief Get the amount of watt dissipated at the given pstate when the host is idling
574  */
575 double sg_host_get_wattmin_at(sg_host_t host, int pstate)
576 {
577   xbt_assert(HostEnergy::EXTENSION_ID.valid(),
578              "The Energy plugin is not active. Please call sg_host_energy_plugin_init() during initialization.");
579   return host->extension<HostEnergy>()->get_watt_min_at(pstate);
580 }
581 /** @ingroup plugin_host_energy
582  *  @brief  Returns the amount of watt dissipated at the given pstate when the host burns CPU at 100%
583  */
584 double sg_host_get_wattmax_at(sg_host_t host, int pstate)
585 {
586   xbt_assert(HostEnergy::EXTENSION_ID.valid(),
587              "The Energy plugin is not active. Please call sg_host_energy_plugin_init() during initialization.");
588   return host->extension<HostEnergy>()->get_watt_max_at(pstate);
589 }
590 /** @ingroup plugin_host_energy
591  *  @brief  Returns the power slope at the given pstate
592  */
593 double sg_host_get_power_range_slope_at(sg_host_t host, int pstate)
594 {
595   xbt_assert(HostEnergy::EXTENSION_ID.valid(),
596              "The Energy plugin is not active. Please call sg_host_energy_plugin_init() during initialization.");
597   return host->extension<HostEnergy>()->get_power_range_slope_at(pstate);
598 }
599 /** @ingroup plugin_host_energy
600  *  @brief Returns the current consumption of the host
601  */
602 double sg_host_get_current_consumption(sg_host_t host)
603 {
604   xbt_assert(HostEnergy::EXTENSION_ID.valid(),
605              "The Energy plugin is not active. Please call sg_host_energy_plugin_init() during initialization.");
606   return host->extension<HostEnergy>()->get_current_watts_value();
607 }