Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
9799f52c4fdace6ed9b89fe1d94182f92b7d88c7
[simgrid.git] / src / surf / plugins / energy.cpp
1 #include "energy.hpp"
2 #include "../cpu_cas01.hpp"
3
4 XBT_LOG_EXTERNAL_CATEGORY(surf_kernel);
5 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_energy, surf,
6                                 "Logging specific to the SURF energy plugin");
7
8 std::map<CpuPtr, CpuEnergyPtr> *surf_energy=NULL;
9
10 static void createCpuCallback(CpuPtr cpu){
11   (*surf_energy)[cpu] = new CpuEnergy(cpu);
12 }
13
14 static void deleteCpuCallback(CpuPtr cpu){
15   std::map<CpuPtr, CpuEnergyPtr>::iterator cpuIt = surf_energy->find(cpu);
16   xbt_assert(cpuIt != surf_energy->end(), "The cpu is not in surf_energy.");
17   XBT_INFO("Total energy (Joules) of host %s: %f", cpu->getName(), cpuIt->second->getConsumedEnergy());
18   delete cpuIt->second;
19   surf_energy->erase(cpuIt);
20 }
21
22 static void updateActionEnergyCallback(CpuActionPtr action){
23   CpuPtr cpu  = getActionCpu(action);
24   CpuEnergyPtr cpu_energy = (*surf_energy)[cpu];
25
26   if(cpu_energy->last_updated < surf_get_clock()) {
27         double cpu_load = lmm_constraint_get_usage(cpu->getConstraint()) / cpu->m_powerPeak;
28     double start_time = cpu_energy->last_updated;
29     double finish_time = surf_get_clock();
30
31     /*XBT_DEBUG("[cpu_update_energy] action time interval=(%f-%f), current power peak=%f, current pstate=%d",
32                   start_time, finish_time, cpu->m_powerPeak, cpu->m_pstate);*/
33     XBT_DEBUG("[cpu_update_energy] action time interval=(%f-%f), current power peak=%f",
34                   start_time, finish_time, cpu->m_powerPeak);
35     double current_energy = cpu_energy->total_energy;
36     double action_energy = cpu_energy->getCurrentWattsValue(cpu_load)*(finish_time-start_time);
37
38     cpu_energy->total_energy = current_energy + action_energy;
39     cpu_energy->last_updated = finish_time;
40
41     XBT_DEBUG("[cpu_update_energy] old_energy_value=%f, action_energy_value=%f", current_energy, action_energy);
42   }
43 }
44
45 /* init Energy plugin */
46 void sg_energy_plugin_init() {
47   if (surf_energy == NULL) {
48     surf_energy = new std::map<CpuPtr, CpuEnergyPtr>();
49     surf_callback_connect(createCpuCallbacks, createCpuCallback);
50     surf_callback_connect(deleteCpuCallbacks, deleteCpuCallback);
51     surf_callback_connect(updateCpuActionCallbacks, updateActionEnergyCallback);
52   }
53 }
54
55 CpuEnergy::CpuEnergy(CpuPtr ptr)
56  : cpu(ptr)
57 {
58   total_energy = 0;
59   power_range_watts_list = getWattsRangeList();
60   last_updated = surf_get_clock();
61 }
62
63 CpuEnergy::~CpuEnergy(){
64   unsigned int iter;
65   xbt_dynar_t power_tuple = NULL;
66   xbt_dynar_foreach(power_range_watts_list, iter, power_tuple)
67     xbt_dynar_free(&power_tuple);
68   xbt_dynar_free(&power_range_watts_list);
69 }
70
71
72 /**
73  * Computes the power consumed by the host according to the current pstate and processor load
74  *
75  */
76 double CpuEnergy::getCurrentWattsValue(double cpu_load)
77 {
78         xbt_dynar_t power_range_list = power_range_watts_list;
79
80         if (power_range_list == NULL)
81         {
82                 XBT_DEBUG("No power range properties specified for host %s", cpu->getName());
83                 return 0;
84         }
85         /*xbt_assert(xbt_dynar_length(power_range_list) == xbt_dynar_length(cpu->p_powerPeakList),
86                                                 "The number of power ranges in the properties does not match the number of pstates for host %s",
87                                                 cpu->getName());*/
88
89     /* retrieve the power values associated with the current pstate */
90     xbt_dynar_t current_power_values = xbt_dynar_get_as(power_range_list, static_cast<CpuCas01Ptr>(cpu)->m_pstate, xbt_dynar_t);
91
92     /* min_power corresponds to the idle power (cpu load = 0) */
93     /* max_power is the power consumed at 100% cpu load       */
94     double min_power = xbt_dynar_get_as(current_power_values, 0, double);
95     double max_power = xbt_dynar_get_as(current_power_values, 1, double);
96     double power_slope = max_power - min_power;
97
98     double current_power = min_power + cpu_load * power_slope;
99
100         XBT_DEBUG("[get_current_watts] min_power=%f, max_power=%f, slope=%f", min_power, max_power, power_slope);
101     XBT_DEBUG("[get_current_watts] Current power (watts) = %f, load = %f", current_power, cpu_load);
102
103         return current_power;
104 }
105
106 double CpuEnergy::getConsumedEnergy()
107 {
108   return total_energy;
109 }
110
111 xbt_dynar_t CpuEnergy::getWattsRangeList()
112 {
113         xbt_dynar_t power_range_list;
114         xbt_dynar_t power_tuple;
115         int i = 0, pstate_nb=0;
116         xbt_dynar_t current_power_values;
117         double min_power, max_power;
118
119         if (cpu->getProperties() == NULL)
120                 return NULL;
121
122         char* all_power_values_str = (char*)xbt_dict_get_or_null(cpu->getProperties(), "power_per_state");
123
124         if (all_power_values_str == NULL)
125                 return NULL;
126
127
128         power_range_list = xbt_dynar_new(sizeof(xbt_dynar_t), NULL);
129         xbt_dynar_t all_power_values = xbt_str_split(all_power_values_str, ",");
130
131         pstate_nb = xbt_dynar_length(all_power_values);
132         for (i=0; i< pstate_nb; i++)
133         {
134                 /* retrieve the power values associated with the current pstate */
135                 current_power_values = xbt_str_split(xbt_dynar_get_as(all_power_values, i, char*), ":");
136                 xbt_assert(xbt_dynar_length(current_power_values) > 1,
137                                 "Power properties incorrectly defined - could not retrieve min and max power values for host %s",
138                                 cpu->getName());
139
140                 /* min_power corresponds to the idle power (cpu load = 0) */
141                 /* max_power is the power consumed at 100% cpu load       */
142                 min_power = atof(xbt_dynar_get_as(current_power_values, 0, char*));
143                 max_power = atof(xbt_dynar_get_as(current_power_values, 1, char*));
144
145                 power_tuple = xbt_dynar_new(sizeof(double), NULL);
146                 xbt_dynar_push_as(power_tuple, double, min_power);
147                 xbt_dynar_push_as(power_tuple, double, max_power);
148
149                 xbt_dynar_push_as(power_range_list, xbt_dynar_t, power_tuple);
150                 xbt_dynar_free(&current_power_values);
151         }
152         xbt_dynar_free(&all_power_values);
153         return power_range_list;
154 }