Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Energy: New function to update the consumption of all hosts at once
authorMartin Quinson <martin.quinson@loria.fr>
Tue, 13 Jun 2017 15:20:49 +0000 (17:20 +0200)
committerMartin Quinson <martin.quinson@loria.fr>
Tue, 13 Jun 2017 15:20:49 +0000 (17:20 +0200)
ChangeLog
include/simgrid/plugins/energy.h
src/bindings/java/jmsg_host.cpp
src/bindings/java/jmsg_host.h
src/bindings/java/org/simgrid/msg/Host.java
src/surf/plugins/host_energy.cpp

index 21cd087..4d92bbf 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -30,6 +30,9 @@ SimGrid (3.16) UNRELEASED
  Virtual Machines
   - Allow multicore VMs, along with the correct sharing computations
 
  Virtual Machines
   - Allow multicore VMs, along with the correct sharing computations
 
+ Energy
+  - New function to update the consumption of all hosts at once.
+
  MSG
   - The netzone are now available from the MSG API.
     The old names still work, but are now deprecated.
  MSG
   - The netzone are now available from the MSG API.
     The old names still work, but are now deprecated.
index 06d1de8..bc1da10 100644 (file)
@@ -13,6 +13,7 @@
 SG_BEGIN_DECL()
 
 XBT_PUBLIC(void) sg_host_energy_plugin_init();
 SG_BEGIN_DECL()
 
 XBT_PUBLIC(void) sg_host_energy_plugin_init();
+XBT_PUBLIC(void) sg_host_energy_update_all();
 XBT_PUBLIC(double) sg_host_get_consumed_energy(sg_host_t host);
 XBT_PUBLIC(double) sg_host_get_wattmin_at(sg_host_t host, int pstate);
 XBT_PUBLIC(double) sg_host_get_wattmax_at(sg_host_t host, int pstate);
 XBT_PUBLIC(double) sg_host_get_consumed_energy(sg_host_t host);
 XBT_PUBLIC(double) sg_host_get_wattmin_at(sg_host_t host, int pstate);
 XBT_PUBLIC(double) sg_host_get_wattmax_at(sg_host_t host, int pstate);
index 2cf5b28..2676d37 100644 (file)
@@ -336,6 +336,11 @@ JNIEXPORT void JNICALL Java_org_simgrid_msg_Host_setAsyncMailbox(JNIEnv * env, j
   env->ReleaseStringUTFChars((jstring) jname, name);
 }
 
   env->ReleaseStringUTFChars((jstring) jname, name);
 }
 
+JNIEXPORT void JNICALL Java_org_simgrid_msg_Host_updateAllEnergyConsumptions(JNIEnv* env, jclass cls)
+{
+  sg_host_energy_update_all();
+}
+
 JNIEXPORT jdouble JNICALL Java_org_simgrid_msg_Host_getConsumedEnergy (JNIEnv *env, jobject jhost)
 {
   msg_host_t host = jhost_get_native(env, jhost);
 JNIEXPORT jdouble JNICALL Java_org_simgrid_msg_Host_getConsumedEnergy (JNIEnv *env, jobject jhost)
 {
   msg_host_t host = jhost_get_native(env, jhost);
index ebbc41e..0b9ed50 100644 (file)
@@ -59,6 +59,7 @@ JNIEXPORT jobjectArray JNICALL Java_org_simgrid_msg_Host_getStorageContent(JNIEn
 JNIEXPORT jobjectArray JNICALL Java_org_simgrid_msg_Host_all(JNIEnv *env, jclass cls);
 JNIEXPORT void JNICALL Java_org_simgrid_msg_Host_setAsyncMailbox(JNIEnv * env, jclass cls_arg, jobject jname);
 
 JNIEXPORT jobjectArray JNICALL Java_org_simgrid_msg_Host_all(JNIEnv *env, jclass cls);
 JNIEXPORT void JNICALL Java_org_simgrid_msg_Host_setAsyncMailbox(JNIEnv * env, jclass cls_arg, jobject jname);
 
+JNIEXPORT void JNICALL Java_org_simgrid_msg_Host_updateAllEnergyConsumptions(JNIEnv* env, jclass cls);
 JNIEXPORT jdouble JNICALL Java_org_simgrid_msg_Host_getConsumedEnergy (JNIEnv *env, jobject jhost);
 
 JNIEXPORT void JNICALL Java_org_simgrid_msg_Host_setPstate(JNIEnv* env, jobject jhost, jint pstate);
 JNIEXPORT jdouble JNICALL Java_org_simgrid_msg_Host_getConsumedEnergy (JNIEnv *env, jobject jhost);
 
 JNIEXPORT void JNICALL Java_org_simgrid_msg_Host_setPstate(JNIEnv* env, jobject jhost, jint pstate);
index 9165a10..2e39fe2 100644 (file)
@@ -133,7 +133,17 @@ public class Host {
        /** This methods returns the list of storages (names) attached to an host */
        public native String[] getAttachedStorage();
 
        /** This methods returns the list of storages (names) attached to an host */
        public native String[] getAttachedStorage();
 
-       /** Returns the amount of Joules consumed by that host so far */
+       /** After this call, sg_host_get_consumed_energy() will not interrupt your process
+        * (until after the next clock update).
+        */
+       static public native void updateAllEnergyConsumptions();
+       /** Returns the amount of Joules consumed by that host so far 
+        *
+        * Please note that since the consumption is lazily updated, it may require a simcall to update it.
+        * The result is that the actor requesting this value will be interrupted,
+        * the value will be updated in kernel mode before returning the control to the requesting actor.
+
+        */
        public native double getConsumedEnergy();
        
        /** Returns the current pstate */
        public native double getConsumedEnergy();
        
        /** Returns the current pstate */
index 9a441b9..f7878d7 100644 (file)
@@ -113,45 +113,54 @@ void HostEnergy::update()
   double finish_time = surf_get_clock();
   double cpu_load;
   double current_speed = host->speed();
   double finish_time = surf_get_clock();
   double cpu_load;
   double current_speed = host->speed();
-  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;
+  if (start_time < finish_time) {
+    // 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();
 
 
-  double instantaneous_consumption;
-  if (this->pstate == -1) // The host was off at the beginning of this time interval
-    instantaneous_consumption = this->watts_off;
-  else
-    instantaneous_consumption = this->getCurrentWattsValue(cpu_load);
+    if (cpu_load > 1) // A machine with a load > 1 consumes as much as a fully loaded machine, not more
+      cpu_load = 1;
 
 
-  double energy_this_step = instantaneous_consumption * (finish_time - start_time);
+    /* 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 == -1) // The host was off at the beginning of this time interval
+      instantaneous_consumption = this->watts_off;
+    else
+      instantaneous_consumption = this->getCurrentWattsValue(cpu_load);
 
 
-  //TODO Trace: Trace energy_this_step from start_time to finish_time in host->name()
+    double energy_this_step = instantaneous_consumption * (finish_time - start_time);
 
 
-  this->total_energy = previous_energy + energy_this_step;
-  this->last_updated = finish_time;
+    // TODO Trace: Trace energy_this_step from start_time to finish_time in host->name()
 
 
-  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);
+    this->total_energy = previous_energy + energy_this_step;
+    this->last_updated = finish_time;
+
+    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);
+  }
 
   /* 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;
 
   /* 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;
@@ -372,7 +381,26 @@ void sg_host_energy_plugin_init()
   simgrid::surf::CpuAction::onStateChange.connect(&onActionStateChange);
 }
 
   simgrid::surf::CpuAction::onStateChange.connect(&onActionStateChange);
 }
 
+/** @brief updates the consumption of all hosts
+ *
+ * After this call, sg_host_get_consumed_energy() will not interrupt your process
+ * (until after the next clock update).
+ */
+void sg_host_energy_update_all()
+{
+  simgrid::simix::kernelImmediate([]() {
+    std::vector<simgrid::s4u::Host*> list;
+    simgrid::s4u::Engine::instance()->hostList(&list);
+    for (auto host : list)
+      host->extension<HostEnergy>()->update();
+  });
+}
+
 /** @brief Returns the total energy consumed by the host so far (in Joules)
 /** @brief Returns the total energy consumed by the host so far (in Joules)
+ *
+ *  Please note that since the consumption is lazily updated, it may require a simcall to update it.
+ *  The result is that the actor requesting this value will be interrupted,
+ *  the value will be updated in kernel mode before returning the control to the requesting actor.
  *
  *  See also @ref SURF_plugin_energy.
  */
  *
  *  See also @ref SURF_plugin_energy.
  */