1 /* Copyright (c) 2010, 2012-2015. The SimGrid Team.
2 * All rights reserved. */
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. */
8 #include "../cpu_cas01.hpp"
10 /** @addtogroup SURF_plugin_energy
13 * This is the energy plugin, enabling to account not only for computation time, but also for the dissipated energy in the simulated platform.
16 XBT_LOG_EXTERNAL_CATEGORY(surf_kernel);
17 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_energy, surf,
18 "Logging specific to the SURF energy plugin");
20 std::map<CpuPtr, CpuEnergyPtr> *surf_energy=NULL;
22 static void energyCpuCreatedCallback(CpuPtr cpu){
23 (*surf_energy)[cpu] = new CpuEnergy(cpu);
26 static void update_consumption(CpuPtr cpu, CpuEnergyPtr cpu_energy) {
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();
31 double current_energy = cpu_energy->total_energy;
32 double action_energy = cpu_energy->getCurrentWattsValue(cpu_load)*(finish_time-start_time);
34 cpu_energy->total_energy = current_energy + action_energy;
35 cpu_energy->last_updated = finish_time;
37 XBT_DEBUG("[cpu_update_energy] period=[%.2f-%.2f]; current power peak=%.0E flop/s; consumption change: %.2f J -> %.2f J",
38 start_time, finish_time, cpu->m_powerPeak, current_energy, action_energy);
41 static void energyCpuDestructedCallback(CpuPtr cpu){
42 std::map<CpuPtr, CpuEnergyPtr>::iterator cpu_energy_it = surf_energy->find(cpu);
43 xbt_assert(cpu_energy_it != surf_energy->end(), "The cpu is not in surf_energy.");
45 CpuEnergyPtr cpu_energy = cpu_energy_it->second;
46 update_consumption(cpu, cpu_energy);
48 XBT_INFO("Total energy of host %s: %f Joules", cpu->getName(), cpu_energy->getConsumedEnergy());
49 delete cpu_energy_it->second;
50 surf_energy->erase(cpu_energy_it);
53 static void energyCpuActionStateChangedCallback(CpuActionPtr action, e_surf_action_state_t old, e_surf_action_state_t cur){
54 CpuPtr cpu = getActionCpu(action);
55 CpuEnergyPtr cpu_energy = (*surf_energy)[cpu];
57 if(cpu_energy->last_updated < surf_get_clock()) {
58 update_consumption(cpu, cpu_energy);
62 static void sg_energy_plugin_exit()
68 /** \ingroup SURF_plugin_energy
69 * \brief Enable energy plugin
70 * \details Enable energy plugin to get joules consumption of each cpu.
72 void sg_energy_plugin_init() {
73 if (surf_energy == NULL) {
74 surf_energy = new std::map<CpuPtr, CpuEnergyPtr>();
75 surf_callback_connect(cpuCreatedCallbacks, energyCpuCreatedCallback);
76 surf_callback_connect(cpuDestructedCallbacks, energyCpuDestructedCallback);
77 surf_callback_connect(cpuActionStateChangedCallbacks, energyCpuActionStateChangedCallback);
78 surf_callback_connect(surfExitCallbacks, sg_energy_plugin_exit);
85 CpuEnergy::CpuEnergy(CpuPtr ptr)
89 power_range_watts_list = getWattsRangeList();
90 last_updated = surf_get_clock();
93 CpuEnergy::~CpuEnergy(){
95 xbt_dynar_t power_tuple = NULL;
96 xbt_dynar_foreach(power_range_watts_list, iter, power_tuple)
97 xbt_dynar_free(&power_tuple);
98 xbt_dynar_free(&power_range_watts_list);
103 * Computes the power consumed by the host according to the current pstate and processor load
106 double CpuEnergy::getCurrentWattsValue(double cpu_load)
108 xbt_dynar_t power_range_list = power_range_watts_list;
110 if (power_range_list == NULL)
112 XBT_DEBUG("No power range properties specified for host %s", cpu->getName());
115 /*xbt_assert(xbt_dynar_length(power_range_list) == xbt_dynar_length(cpu->p_powerPeakList),
116 "The number of power ranges in the properties does not match the number of pstates for host %s",
119 /* retrieve the power values associated with the current pstate */
120 xbt_dynar_t current_power_values = xbt_dynar_get_as(power_range_list, static_cast<CpuCas01Ptr>(cpu)->getPState(), xbt_dynar_t);
122 /* min_power corresponds to the idle power (cpu load = 0) */
123 /* max_power is the power consumed at 100% cpu load */
124 double min_power = xbt_dynar_get_as(current_power_values, 0, double);
125 double max_power = xbt_dynar_get_as(current_power_values, 1, double);
126 double power_slope = max_power - min_power;
128 double current_power = min_power + cpu_load * power_slope;
130 XBT_DEBUG("[get_current_watts] min_power=%f, max_power=%f, slope=%f", min_power, max_power, power_slope);
131 XBT_DEBUG("[get_current_watts] Current power (watts) = %f, load = %f", current_power, cpu_load);
133 return current_power;
136 double CpuEnergy::getConsumedEnergy()
141 xbt_dynar_t CpuEnergy::getWattsRangeList()
143 xbt_dynar_t power_range_list;
144 xbt_dynar_t power_tuple;
145 int i = 0, pstate_nb=0;
146 xbt_dynar_t current_power_values;
147 double min_power, max_power;
149 if (cpu->getProperties() == NULL)
152 char* all_power_values_str = (char*)xbt_dict_get_or_null(cpu->getProperties(), "watt_per_state");
154 if (all_power_values_str == NULL)
158 power_range_list = xbt_dynar_new(sizeof(xbt_dynar_t), NULL);
159 xbt_dynar_t all_power_values = xbt_str_split(all_power_values_str, ",");
161 pstate_nb = xbt_dynar_length(all_power_values);
162 for (i=0; i< pstate_nb; i++)
164 /* retrieve the power values associated with the current pstate */
165 current_power_values = xbt_str_split(xbt_dynar_get_as(all_power_values, i, char*), ":");
166 xbt_assert(xbt_dynar_length(current_power_values) > 1,
167 "Power properties incorrectly defined - could not retrieve min and max power values for host %s",
170 /* min_power corresponds to the idle power (cpu load = 0) */
171 /* max_power is the power consumed at 100% cpu load */
172 min_power = atof(xbt_dynar_get_as(current_power_values, 0, char*));
173 max_power = atof(xbt_dynar_get_as(current_power_values, 1, char*));
175 power_tuple = xbt_dynar_new(sizeof(double), NULL);
176 xbt_dynar_push_as(power_tuple, double, min_power);
177 xbt_dynar_push_as(power_tuple, double, max_power);
179 xbt_dynar_push_as(power_range_list, xbt_dynar_t, power_tuple);
180 xbt_dynar_free(¤t_power_values);
182 xbt_dynar_free(&all_power_values);
183 return power_range_list;