Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Introduce sg_storage_size_t type
[simgrid.git] / src / surf / cpu_cas01.c
index be08fc7..3430431 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011. The SimGrid Team.
+/* Copyright (c) 2009-2013. The SimGrid Team.
  * All rights reserved.                                                     */
 
 /* This program is free software; you can redistribute it and/or modify it
@@ -7,42 +7,38 @@
 #include "surf_private.h"
 #include "surf/surf_resource.h"
 #include "maxmin_private.h"
+#include "simgrid/sg_config.h"
+#include "cpu_cas01_private.h"
+
+#include "string.h"
+#include "stdlib.h"
 
 surf_model_t surf_cpu_model = NULL;
 
-#undef GENERIC_LMM_ACTION
-#undef GENERIC_ACTION
-#undef ACTION_GET_CPU
-#define GENERIC_LMM_ACTION(action) action->generic_lmm_action
-#define GENERIC_ACTION(action) GENERIC_LMM_ACTION(action).generic_action
-#define ACTION_GET_CPU(action) ((surf_action_cpu_Cas01_t) action)->cpu
-
-typedef struct surf_action_cpu_cas01 {
-  s_surf_action_lmm_t generic_lmm_action;
-} s_surf_action_cpu_Cas01_t, *surf_action_cpu_Cas01_t;
-
-typedef struct cpu_Cas01 {
-  s_surf_resource_t generic_resource;
-  s_xbt_swag_hookup_t modified_cpu_hookup;
-  double power_peak;
-  double power_scale;
-  tmgr_trace_event_t power_event;
-  int core;
-  e_surf_resource_state_t state_current;
-  tmgr_trace_event_t state_event;
-  lmm_constraint_t constraint;
-} s_cpu_Cas01_t, *cpu_Cas01_t;
 
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_cpu, surf,
                                 "Logging specific to the SURF CPU IMPROVED module");
 
-
-
 static xbt_swag_t
     cpu_running_action_set_that_does_not_need_being_checked = NULL;
 
+/* Additionnal callback function to cleanup some data, called from surf_resource_free */
+
+static void cpu_cas01_cleanup(void* r){
+  cpu_Cas01_t cpu = (cpu_Cas01_t)r;
+  unsigned int iter;
+  xbt_dynar_t power_tuple = NULL;
+  xbt_dynar_foreach(cpu->energy->power_range_watts_list, iter, power_tuple)
+    xbt_dynar_free(&power_tuple);
+  xbt_dynar_free(&cpu->energy->power_range_watts_list);
+  xbt_dynar_free(&cpu->power_peak_list);
+  xbt_free(cpu->energy);
+  return;
+}
 
-static void *cpu_create_resource(const char *name, double power_peak,
+/* This function is registered as a callback to sg_platf_new_host() and never called directly */
+static void *cpu_create_resource(const char *name, xbt_dynar_t power_peak,
+                                                                int pstate,
                                  double power_scale,
                                  tmgr_trace_t power_trace,
                                  int core,
@@ -52,13 +48,23 @@ static void *cpu_create_resource(const char *name, double power_peak,
 {
   cpu_Cas01_t cpu = NULL;
 
-  xbt_assert(!surf_cpu_resource_by_name(name),
+  xbt_assert(!surf_cpu_resource_priv(surf_cpu_resource_by_name(name)),
              "Host '%s' declared several times in the platform file",
              name);
   cpu = (cpu_Cas01_t) surf_resource_new(sizeof(s_cpu_Cas01_t),
                                         surf_cpu_model, name,
-                                        cpu_properties);
-  cpu->power_peak = power_peak;
+                                        cpu_properties,  &cpu_cas01_cleanup);
+  cpu->power_peak = xbt_dynar_get_as(power_peak, pstate, double);
+  cpu->power_peak_list = power_peak;
+  cpu->pstate = pstate;
+
+  cpu->energy = xbt_new(s_energy_cpu_cas01_t, 1);
+  cpu->energy->total_energy = 0;
+  cpu->energy->power_range_watts_list = cpu_get_watts_range_list(cpu);
+  cpu->energy->last_updated = surf_get_clock();
+
+  XBT_DEBUG("CPU create: peak=%lf, pstate=%d",cpu->power_peak, cpu->pstate);
+
   xbt_assert(cpu->power_peak > 0, "Power has to be >0");
   cpu->power_scale = power_scale;
   cpu->core = core;
@@ -79,7 +85,7 @@ static void *cpu_create_resource(const char *name, double power_peak,
 
   xbt_lib_set(host_lib, name, SURF_CPU_LEVEL, cpu);
 
-  return cpu;
+  return xbt_lib_get_elm_or_null(host_lib, name);;
 }
 
 
@@ -87,6 +93,7 @@ static void parse_cpu_init(sg_platf_host_cbarg_t host)
 {
   cpu_create_resource(host->id,
                       host->power_peak,
+                      host->pstate,
                       host->power_scale,
                       host->power_trace,
                       host->core_amount,
@@ -157,94 +164,116 @@ static double cpu_share_resources_full(double now)
 
 static void cpu_update_actions_state_lazy(double now, double delta)
 {
-  surf_action_cpu_Cas01_t action;
-  while ((xbt_heap_size(surf_cpu_model->model_private->action_heap) > 0)
-         && (double_equals(xbt_heap_maxkey(surf_cpu_model->model_private->action_heap), now))) {
-    action = xbt_heap_pop(surf_cpu_model->model_private->action_heap);
-    XBT_DEBUG("Action %p: finish", action);
-    GENERIC_ACTION(action).finish = surf_get_clock();
-#ifdef HAVE_TRACING
-    if (TRACE_is_enabled()) {
-      cpu_Cas01_t cpu =
-          lmm_constraint_id(lmm_get_cnst_from_var
-                            (surf_cpu_model->model_private->maxmin_system,
-                             GENERIC_LMM_ACTION(action).variable, 0));
-      TRACE_surf_host_set_utilization(cpu->generic_resource.name,
-                                      ((surf_action_t)action)->category,
-                                      lmm_variable_getvalue(GENERIC_LMM_ACTION(action).variable),
-                                      GENERIC_LMM_ACTION(action).last_update,
-                                      now - GENERIC_LMM_ACTION(action).last_update);
-    }
-#endif
-    /* set the remains to 0 due to precision problems when updating the remaining amount */
-    GENERIC_ACTION(action).remains = 0;
-    surf_action_state_set((surf_action_t) action, SURF_ACTION_DONE);
-    surf_action_lmm_heap_remove(surf_cpu_model->model_private->action_heap,(surf_action_lmm_t)action); //FIXME: strange call since action was already popped
-  }
-#ifdef HAVE_TRACING
-  if (TRACE_is_enabled()) {
-    //defining the last timestamp that we can safely dump to trace file
-    //without losing the event ascending order (considering all CPU's)
-    double smaller = -1;
-    xbt_swag_t running_actions = surf_cpu_model->states.running_action_set;
-    xbt_swag_foreach(action, running_actions) {
-        if (smaller < 0) {
-          smaller = GENERIC_LMM_ACTION(action).last_update;
-          continue;
-        }
-        if (GENERIC_LMM_ACTION(action).last_update < smaller) {
-          smaller = GENERIC_LMM_ACTION(action).last_update;
-        }
-    }
-    if (smaller > 0) {
-      TRACE_last_timestamp_to_dump = smaller;
-    }
-  }
-#endif
-  return;
+  generic_update_actions_state_lazy(now, delta, surf_cpu_model);
 }
 
 static void cpu_update_actions_state_full(double now, double delta)
 {
-  surf_action_cpu_Cas01_t action = NULL;
-  surf_action_cpu_Cas01_t next_action = NULL;
-  xbt_swag_t running_actions = surf_cpu_model->states.running_action_set;
-  xbt_swag_foreach_safe(action, next_action, running_actions) {
-#ifdef HAVE_TRACING
-    if (TRACE_is_enabled()) {
-      cpu_Cas01_t x =
-          lmm_constraint_id(lmm_get_cnst_from_var
-                            (surf_cpu_model->model_private->maxmin_system,
-                             GENERIC_LMM_ACTION(action).variable, 0));
-
-      TRACE_surf_host_set_utilization(x->generic_resource.name,
-                                      ((surf_action_t)action)->category,
-                                      lmm_variable_getvalue(GENERIC_LMM_ACTION(action).
-                                       variable),
-                                      now - delta,
-                                      delta);
-      TRACE_last_timestamp_to_dump = now - delta;
-    }
-#endif
-    double_update(&(GENERIC_ACTION(action).remains),
-                  lmm_variable_getvalue(GENERIC_LMM_ACTION(action).
-                                        variable) * delta);
-    if (GENERIC_LMM_ACTION(action).generic_action.max_duration !=
-        NO_MAX_DURATION)
-      double_update(&(GENERIC_ACTION(action).max_duration), delta);
-    if ((GENERIC_ACTION(action).remains <= 0) &&
-        (lmm_get_variable_weight(GENERIC_LMM_ACTION(action).variable) >
-         0)) {
-      GENERIC_ACTION(action).finish = surf_get_clock();
-      surf_action_state_set((surf_action_t) action, SURF_ACTION_DONE);
-    } else if ((GENERIC_ACTION(action).max_duration != NO_MAX_DURATION) &&
-               (GENERIC_ACTION(action).max_duration <= 0)) {
-      GENERIC_ACTION(action).finish = surf_get_clock();
-      surf_action_state_set((surf_action_t) action, SURF_ACTION_DONE);
-    }
-  }
+  generic_update_actions_state_full(now, delta, surf_cpu_model);
+}
+
+xbt_dynar_t cpu_get_watts_range_list(cpu_Cas01_t cpu_model)
+{
+       xbt_dynar_t power_range_list;
+       xbt_dynar_t power_tuple;
+       int i = 0, pstate_nb=0;
+       xbt_dynar_t current_power_values;
+       double min_power, max_power;
+       xbt_dict_t props = cpu_model->generic_resource.properties;
+
+       if (props == NULL)
+               return NULL;
+
+       char* all_power_values_str = xbt_dict_get_or_null(props, "power_per_state");
+
+       if (all_power_values_str == NULL)
+               return NULL;
+
+
+       power_range_list = xbt_dynar_new(sizeof(xbt_dynar_t), NULL);
+       xbt_dynar_t all_power_values = xbt_str_split(all_power_values_str, ",");
+
+       pstate_nb = xbt_dynar_length(all_power_values);
+       for (i=0; i< pstate_nb; i++)
+       {
+               /* retrieve the power values associated with the current pstate */
+               current_power_values = xbt_str_split(xbt_dynar_get_as(all_power_values, i, char*), ":");
+               xbt_assert(xbt_dynar_length(current_power_values) > 1,
+                               "Power properties incorrectly defined - could not retrieve min and max power values for host %s",
+                               cpu_model->generic_resource.name);
+
+               /* min_power corresponds to the idle power (cpu load = 0) */
+               /* max_power is the power consumed at 100% cpu load       */
+               min_power = atof(xbt_dynar_get_as(current_power_values, 0, char*));
+               max_power = atof(xbt_dynar_get_as(current_power_values, 1, char*));
+
+               power_tuple = xbt_dynar_new(sizeof(double), NULL);
+               xbt_dynar_push_as(power_tuple, double, min_power);
+               xbt_dynar_push_as(power_tuple, double, max_power);
+
+               xbt_dynar_push_as(power_range_list, xbt_dynar_t, power_tuple);
+               xbt_dynar_free(&current_power_values);
+       }
+       xbt_dynar_free(&all_power_values);
+       return power_range_list;
+
+}
+
+/**
+ * Computes the power consumed by the host according to the current pstate and processor load
+ *
+ */
+static double cpu_get_current_watts_value(cpu_Cas01_t cpu_model, double cpu_load)
+{
+       xbt_dynar_t power_range_list = cpu_model->energy->power_range_watts_list;
+
+       if (power_range_list == NULL)
+       {
+               XBT_DEBUG("No power range properties specified for host %s", cpu_model->generic_resource.name);
+               return 0;
+       }
+       xbt_assert(xbt_dynar_length(power_range_list) == xbt_dynar_length(cpu_model->power_peak_list),
+                                               "The number of power ranges in the properties does not match the number of pstates for host %s",
+                                               cpu_model->generic_resource.name);
+
+    /* retrieve the power values associated with the current pstate */
+    xbt_dynar_t current_power_values = xbt_dynar_get_as(power_range_list, cpu_model->pstate, xbt_dynar_t);
+
+    /* min_power corresponds to the idle power (cpu load = 0) */
+    /* max_power is the power consumed at 100% cpu load       */
+    double min_power = xbt_dynar_get_as(current_power_values, 0, double);
+    double max_power = xbt_dynar_get_as(current_power_values, 1, double);
+    double power_slope = max_power - min_power;
+
+    double current_power = min_power + cpu_load * power_slope;
+
+       XBT_DEBUG("[get_current_watts] min_power=%lf, max_power=%lf, slope=%lf", min_power, max_power, power_slope);
+    XBT_DEBUG("[get_current_watts] Current power (watts) = %lf, load = %lf", current_power, cpu_load);
+
+       return current_power;
+
+}
+
+/**
+ * Updates the total energy consumed as the sum of the current energy and
+ *                                              the energy consumed by the current action
+ */
+void cpu_update_energy(cpu_Cas01_t cpu_model, double cpu_load)
+{
+
+  double start_time = cpu_model->energy->last_updated;
+  double finish_time = surf_get_clock();
+
+  XBT_DEBUG("[cpu_update_energy] action time interval=(%lf-%lf), current power peak=%lf, current pstate=%d",
+                 start_time, finish_time, cpu_model->power_peak, cpu_model->pstate);
+  double current_energy = cpu_model->energy->total_energy;
+  double action_energy = cpu_get_current_watts_value(cpu_model, cpu_load)*(finish_time-start_time);
+
+  cpu_model->energy->total_energy = current_energy + action_energy;
+  cpu_model->energy->last_updated = finish_time;
+
+  XBT_DEBUG("[cpu_update_energy] old_energy_value=%lf, action_energy_value=%lf", current_energy, action_energy);
 
-  return;
 }
 
 static void cpu_update_resource_state(void *id,
@@ -275,9 +304,11 @@ static void cpu_update_resource_state(void *id,
     if (tmgr_trace_event_free(event_type))
       cpu->power_event = NULL;
   } else if (event_type == cpu->state_event) {
-    if (value > 0)
+    if (value > 0) {
+      if(cpu->state_current == SURF_RESOURCE_OFF)
+        xbt_dynar_push_as(host_that_restart, char*, (cpu->generic_resource.name));
       cpu->state_current = SURF_RESOURCE_ON;
-    else {
+    else {
       lmm_constraint_t cnst = cpu->constraint;
 
       cpu->state_current = SURF_RESOURCE_OFF;
@@ -307,7 +338,9 @@ static void cpu_update_resource_state(void *id,
 static surf_action_t cpu_execute(void *cpu, double size)
 {
   surf_action_cpu_Cas01_t action = NULL;
-  cpu_Cas01_t CPU = cpu;
+  //xbt_dict_cursor_t cursor = NULL;
+  cpu_Cas01_t CPU = surf_cpu_resource_priv(cpu);
+  //xbt_dict_t props = CPU->generic_resource.properties;
 
   XBT_IN("(%s,%g)", surf_resource_name(CPU), size);
   action =
@@ -327,6 +360,7 @@ static surf_action_t cpu_execute(void *cpu, double size)
     GENERIC_LMM_ACTION(action).last_update = surf_get_clock();
     GENERIC_LMM_ACTION(action).last_value = 0.0;
   }
+
   lmm_expand(surf_cpu_model->model_private->maxmin_system, CPU->constraint,
              GENERIC_LMM_ACTION(action).variable, 1.0);
   XBT_OUT();
@@ -340,7 +374,7 @@ static surf_action_t cpu_action_sleep(void *cpu, double duration)
   if (duration > 0)
     duration = MAX(duration, MAXMIN_PRECISION);
 
-  XBT_IN("(%s,%g)", surf_resource_name(cpu), duration);
+  XBT_IN("(%s,%g)", surf_resource_name(surf_cpu_resource_priv(cpu)), duration);
   action = (surf_action_cpu_Cas01_t) cpu_execute(cpu, 1.0);
   // FIXME: sleep variables should not consume 1.0 in lmm_expand
   GENERIC_ACTION(action).max_duration = duration;
@@ -370,18 +404,58 @@ static surf_action_t cpu_action_sleep(void *cpu, double duration)
 
 static e_surf_resource_state_t cpu_get_state(void *cpu)
 {
-  return ((cpu_Cas01_t) cpu)->state_current;
+  return ((cpu_Cas01_t)surf_cpu_resource_priv(cpu))->state_current;
 }
 
 static double cpu_get_speed(void *cpu, double load)
 {
-  return load * (((cpu_Cas01_t) cpu)->power_peak);
+  return load * ((cpu_Cas01_t)surf_cpu_resource_priv(cpu))->power_peak;
+}
+
+static int cpu_get_core(void *cpu)
+{
+  return ((cpu_Cas01_t)surf_cpu_resource_priv(cpu))->core;
 }
 
+
 static double cpu_get_available_speed(void *cpu)
 {
   /* number between 0 and 1 */
-  return ((cpu_Cas01_t) cpu)->power_scale;
+  return ((cpu_Cas01_t)surf_cpu_resource_priv(cpu))->power_scale;
+}
+
+static double cpu_get_current_power_peak(void *cpu)
+{
+  return ((cpu_Cas01_t)surf_cpu_resource_priv(cpu))->power_peak;
+}
+
+static double cpu_get_power_peak_at(void *cpu, int pstate_index)
+{
+  xbt_dynar_t plist = ((cpu_Cas01_t)surf_cpu_resource_priv(cpu))->power_peak_list;
+  xbt_assert((pstate_index <= xbt_dynar_length(plist)), "Invalid parameters (pstate index out of bounds)");
+
+  return xbt_dynar_get_as(plist, pstate_index, double);
+}
+
+static int cpu_get_nb_pstates(void *cpu)
+{
+  return xbt_dynar_length(((cpu_Cas01_t)surf_cpu_resource_priv(cpu))->power_peak_list);
+}
+
+static void cpu_set_power_peak_at(void *cpu, int pstate_index)
+{
+  cpu_Cas01_t cpu_implem = (cpu_Cas01_t)surf_cpu_resource_priv(cpu);
+  xbt_dynar_t plist = cpu_implem->power_peak_list;
+  xbt_assert((pstate_index <= xbt_dynar_length(plist)), "Invalid parameters (pstate index out of bounds)");
+
+  double new_power_peak = xbt_dynar_get_as(plist, pstate_index, double);
+  cpu_implem->pstate = pstate_index;
+  cpu_implem->power_peak = new_power_peak;
+}
+
+static double cpu_get_consumed_energy(void *cpu)
+{
+  return ((cpu_Cas01_t)surf_cpu_resource_priv(cpu))->energy->total_energy;
 }
 
 static void cpu_finalize(void)
@@ -405,9 +479,9 @@ static void surf_cpu_model_init_internal()
   s_surf_action_t action;
   s_surf_action_cpu_Cas01_t comp;
 
-  char *optim = xbt_cfg_get_string(_surf_cfg_set, "cpu/optim");
+  char *optim = xbt_cfg_get_string(_sg_cfg_set, "cpu/optim");
   int select =
-      xbt_cfg_get_int(_surf_cfg_set, "cpu/maxmin_selective_update");
+      xbt_cfg_get_boolean(_sg_cfg_set, "cpu/maxmin_selective_update");
 
   surf_cpu_model = surf_model_init();
 
@@ -420,7 +494,7 @@ static void surf_cpu_model_init_internal()
     xbt_assert((select == 1)
                ||
                (xbt_cfg_is_default_value
-                (_surf_cfg_set, "cpu/maxmin_selective_update")),
+                (_sg_cfg_set, "cpu/maxmin_selective_update")),
                "Disabling selective update while using the lazy update mechanism is dumb!");
   } else {
     xbt_die("Unsupported optimization (%s) for this model", optim);
@@ -468,10 +542,16 @@ static void surf_cpu_model_init_internal()
   surf_cpu_model->extension.cpu.sleep = cpu_action_sleep;
 
   surf_cpu_model->extension.cpu.get_state = cpu_get_state;
+  surf_cpu_model->extension.cpu.get_core = cpu_get_core;
   surf_cpu_model->extension.cpu.get_speed = cpu_get_speed;
   surf_cpu_model->extension.cpu.get_available_speed =
       cpu_get_available_speed;
-  surf_cpu_model->extension.cpu.create_resource = cpu_create_resource;
+  surf_cpu_model->extension.cpu.get_current_power_peak = cpu_get_current_power_peak;
+  surf_cpu_model->extension.cpu.get_power_peak_at = cpu_get_power_peak_at;
+  surf_cpu_model->extension.cpu.get_nb_pstates = cpu_get_nb_pstates;
+  surf_cpu_model->extension.cpu.set_power_peak_at = cpu_set_power_peak_at;
+  surf_cpu_model->extension.cpu.get_consumed_energy = cpu_get_consumed_energy;
+
   surf_cpu_model->extension.cpu.add_traces = cpu_add_traces_cpu;
 
   if (!surf_cpu_model->model_private->maxmin_system) {
@@ -505,7 +585,7 @@ static void surf_cpu_model_init_internal()
 
 void surf_cpu_model_init_Cas01()
 {
-  char *optim = xbt_cfg_get_string(_surf_cfg_set, "cpu/optim");
+  char *optim = xbt_cfg_get_string(_sg_cfg_set, "cpu/optim");
 
   if (surf_cpu_model)
     return;