Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Free surf_energy on exit.
[simgrid.git] / src / surf / plugins / energy.cpp
1 /* Copyright (c) 2010, 2012-2014. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include "energy.hpp"
8 #include "../cpu_cas01.hpp"
9
10 /** @addtogroup SURF_plugin_energy
11  *    
12  *  
13  *  BlaBla energy
14  */
15
16 XBT_LOG_EXTERNAL_CATEGORY(surf_kernel);
17 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_energy, surf,
18                                 "Logging specific to the SURF energy plugin");
19
20 std::map<CpuPtr, CpuEnergyPtr> *surf_energy=NULL;
21
22 static void energyCpuCreatedCallback(CpuPtr cpu){
23   (*surf_energy)[cpu] = new CpuEnergy(cpu);
24 }
25
26 static void energyCpuDestructedCallback(CpuPtr cpu){
27   std::map<CpuPtr, CpuEnergyPtr>::iterator cpuIt = surf_energy->find(cpu);
28   xbt_assert(cpuIt != surf_energy->end(), "The cpu is not in surf_energy.");
29   XBT_INFO("Total energy (Joules) of host %s: %f", cpu->getName(), cpuIt->second->getConsumedEnergy());
30   delete cpuIt->second;
31   surf_energy->erase(cpuIt);
32 }
33
34 static void energyCpuActionStateChangedCallback(CpuActionPtr action){
35   CpuPtr cpu  = getActionCpu(action);
36   CpuEnergyPtr cpu_energy = (*surf_energy)[cpu];
37
38   if(cpu_energy->last_updated < surf_get_clock()) {
39         double cpu_load = lmm_constraint_get_usage(cpu->getConstraint()) / cpu->m_powerPeak;
40     double start_time = cpu_energy->last_updated;
41     double finish_time = surf_get_clock();
42
43     /*XBT_DEBUG("[cpu_update_energy] action time interval=(%f-%f), current power peak=%f, current pstate=%d",
44                   start_time, finish_time, cpu->m_powerPeak, cpu->m_pstate);*/
45     XBT_DEBUG("[cpu_update_energy] action time interval=(%f-%f), current power peak=%f",
46                   start_time, finish_time, cpu->m_powerPeak);
47     double current_energy = cpu_energy->total_energy;
48     double action_energy = cpu_energy->getCurrentWattsValue(cpu_load)*(finish_time-start_time);
49
50     cpu_energy->total_energy = current_energy + action_energy;
51     cpu_energy->last_updated = finish_time;
52
53     XBT_DEBUG("[cpu_update_energy] old_energy_value=%f, action_energy_value=%f", current_energy, action_energy);
54   }
55 }
56
57 static void sg_energy_plugin_exit()
58 {
59   delete surf_energy;
60   surf_energy = NULL;
61 }
62
63 /** \ingroup SURF_plugin_energy
64  * \brief Enable energy plugin
65  * \details Enable energy plugin to get joules consumption of each cpu.
66  */
67 void sg_energy_plugin_init() {
68   if (surf_energy == NULL) {
69     surf_energy = new std::map<CpuPtr, CpuEnergyPtr>();
70     surf_callback_connect(cpuCreatedCallbacks, energyCpuCreatedCallback);
71     surf_callback_connect(cpuDestructedCallbacks, energyCpuDestructedCallback);
72     surf_callback_connect(cpuActionStateChangedCallbacks, energyCpuActionStateChangedCallback);
73     surf_callback_connect(surfExitCallbacks, sg_energy_plugin_exit);
74   }
75 }
76
77 /**
78  *
79  */
80 CpuEnergy::CpuEnergy(CpuPtr ptr)
81  : cpu(ptr)
82 {
83   total_energy = 0;
84   power_range_watts_list = getWattsRangeList();
85   last_updated = surf_get_clock();
86 }
87
88 CpuEnergy::~CpuEnergy(){
89   unsigned int iter;
90   xbt_dynar_t power_tuple = NULL;
91   xbt_dynar_foreach(power_range_watts_list, iter, power_tuple)
92     xbt_dynar_free(&power_tuple);
93   xbt_dynar_free(&power_range_watts_list);
94 }
95
96
97 /**
98  * Computes the power consumed by the host according to the current pstate and processor load
99  *
100  */
101 double CpuEnergy::getCurrentWattsValue(double cpu_load)
102 {
103         xbt_dynar_t power_range_list = power_range_watts_list;
104
105         if (power_range_list == NULL)
106         {
107                 XBT_DEBUG("No power range properties specified for host %s", cpu->getName());
108                 return 0;
109         }
110         /*xbt_assert(xbt_dynar_length(power_range_list) == xbt_dynar_length(cpu->p_powerPeakList),
111                                                 "The number of power ranges in the properties does not match the number of pstates for host %s",
112                                                 cpu->getName());*/
113
114     /* retrieve the power values associated with the current pstate */
115     xbt_dynar_t current_power_values = xbt_dynar_get_as(power_range_list, static_cast<CpuCas01Ptr>(cpu)->m_pstate, xbt_dynar_t);
116
117     /* min_power corresponds to the idle power (cpu load = 0) */
118     /* max_power is the power consumed at 100% cpu load       */
119     double min_power = xbt_dynar_get_as(current_power_values, 0, double);
120     double max_power = xbt_dynar_get_as(current_power_values, 1, double);
121     double power_slope = max_power - min_power;
122
123     double current_power = min_power + cpu_load * power_slope;
124
125         XBT_DEBUG("[get_current_watts] min_power=%f, max_power=%f, slope=%f", min_power, max_power, power_slope);
126     XBT_DEBUG("[get_current_watts] Current power (watts) = %f, load = %f", current_power, cpu_load);
127
128         return current_power;
129 }
130
131 double CpuEnergy::getConsumedEnergy()
132 {
133   return total_energy;
134 }
135
136 xbt_dynar_t CpuEnergy::getWattsRangeList()
137 {
138         xbt_dynar_t power_range_list;
139         xbt_dynar_t power_tuple;
140         int i = 0, pstate_nb=0;
141         xbt_dynar_t current_power_values;
142         double min_power, max_power;
143
144         if (cpu->getProperties() == NULL)
145                 return NULL;
146
147         char* all_power_values_str = (char*)xbt_dict_get_or_null(cpu->getProperties(), "power_per_state");
148
149         if (all_power_values_str == NULL)
150                 return NULL;
151
152
153         power_range_list = xbt_dynar_new(sizeof(xbt_dynar_t), NULL);
154         xbt_dynar_t all_power_values = xbt_str_split(all_power_values_str, ",");
155
156         pstate_nb = xbt_dynar_length(all_power_values);
157         for (i=0; i< pstate_nb; i++)
158         {
159                 /* retrieve the power values associated with the current pstate */
160                 current_power_values = xbt_str_split(xbt_dynar_get_as(all_power_values, i, char*), ":");
161                 xbt_assert(xbt_dynar_length(current_power_values) > 1,
162                                 "Power properties incorrectly defined - could not retrieve min and max power values for host %s",
163                                 cpu->getName());
164
165                 /* min_power corresponds to the idle power (cpu load = 0) */
166                 /* max_power is the power consumed at 100% cpu load       */
167                 min_power = atof(xbt_dynar_get_as(current_power_values, 0, char*));
168                 max_power = atof(xbt_dynar_get_as(current_power_values, 1, char*));
169
170                 power_tuple = xbt_dynar_new(sizeof(double), NULL);
171                 xbt_dynar_push_as(power_tuple, double, min_power);
172                 xbt_dynar_push_as(power_tuple, double, max_power);
173
174                 xbt_dynar_push_as(power_range_list, xbt_dynar_t, power_tuple);
175                 xbt_dynar_free(&current_power_values);
176         }
177         xbt_dynar_free(&all_power_values);
178         return power_range_list;
179 }