X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/82230d737404aa70c3c2b5824d97109f1f129d58..b63adff37a6c05384b40d5c5bd5be49b246cf9fc:/src/surf/plugins/link_energy.cpp diff --git a/src/surf/plugins/link_energy.cpp b/src/surf/plugins/link_energy.cpp index f7bc8ebcc4..0640a8817b 100644 --- a/src/surf/plugins/link_energy.cpp +++ b/src/surf/plugins/link_energy.cpp @@ -1,30 +1,27 @@ -/* Copyright (c) 2017. The SimGrid Team. All rights reserved. */ +/* Copyright (c) 2017-2018. The SimGrid Team. All rights reserved. */ /* This program is free software; you can redistribute it and/or modify it * under the terms of the license (GNU LGPL) which comes with this package. */ #include "simgrid/plugins/energy.h" #include "simgrid/s4u/Engine.hpp" -#include "simgrid/simix.hpp" #include "src/surf/network_interface.hpp" +#include "surf/surf.hpp" + #include #include -#include -#include -#include -#include /** @addtogroup SURF_plugin_energy - This is the energy plugin, enabling to account for the dissipated energy in the simulated platform. + This is the link energy plugin, accounting for the dissipated energy in the simulated platform. The energy consumption of a link depends directly on its current traffic load. Specify that consumption in your platform file as follows: \verbatim - - + + \endverbatim @@ -36,7 +33,7 @@ To simulate the energy-related elements, first call the simgrid#energy#sg_link_energy_plugin_init() before your #MSG_init(), - and then use the following function to retrieve the consumption of a given link: MSG_link_get_consumed_energy(). + and then use the following function to retrieve the consumption of a given link: sg_link_get_consumed_energy(). */ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(link_energy, surf, "Logging specific to the SURF LinkEnergy plugin"); @@ -44,14 +41,6 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(link_energy, surf, "Logging specific to the SURF namespace simgrid { namespace plugin { -class LinkPowerRange { -public: - double idle; - double busy; - - LinkPowerRange(double idle, double busy) : idle(idle), busy(busy) {} -}; - class LinkEnergy { public: static simgrid::xbt::Extension EXTENSION_ID; @@ -59,25 +48,26 @@ public: explicit LinkEnergy(simgrid::s4u::Link* ptr); ~LinkEnergy(); - double getALinkTotalPower(); void initWattsRangeList(); - double getTotalEnergy(); + double getConsumedEnergy(); void update(); private: double getPower(); - simgrid::s4u::Link* link{}; + simgrid::s4u::Link* link_{}; - std::vector power_range_watts_list{}; + bool inited_{false}; + double idle_{0.0}; + double busy_{0.0}; - double total_energy{0.0}; - double last_updated{0.0}; /*< Timestamp of the last energy update event*/ + double totalEnergy_{0.0}; + double lastUpdated_{0.0}; /*< Timestamp of the last energy update event*/ }; simgrid::xbt::Extension LinkEnergy::EXTENSION_ID; -LinkEnergy::LinkEnergy(simgrid::s4u::Link* ptr) : link(ptr), last_updated(surf_get_clock()) +LinkEnergy::LinkEnergy(simgrid::s4u::Link* ptr) : link_(ptr), lastUpdated_(surf_get_clock()) { } @@ -87,17 +77,18 @@ void LinkEnergy::update() { double power = getPower(); double now = surf_get_clock(); - total_energy += power * (now - last_updated); - last_updated = now; + totalEnergy_ += power * (now - lastUpdated_); + lastUpdated_ = now; } void LinkEnergy::initWattsRangeList() { - if (!power_range_watts_list.empty()) + if (inited_) return; + inited_ = true; - const char* all_power_values_str = this->link->getProperty("watt_range"); + const char* all_power_values_str = this->link_->getProperty("watt_range"); if (all_power_values_str == nullptr) return; @@ -109,23 +100,20 @@ void LinkEnergy::initWattsRangeList() /* retrieve the power values associated */ std::vector current_power_values; boost::split(current_power_values, current_power_values_str, boost::is_any_of(":")); - xbt_assert(current_power_values.size() == 2, "Power properties incorrectly defined - " - "could not retrieve idle and busy power values for link %s", - this->link->getCname()); + xbt_assert(current_power_values.size() == 2, + "Power properties incorrectly defined - could not retrieve idle and busy power values for link %s", + this->link_->get_cname()); /* min_power corresponds to the idle power (link load = 0) */ /* max_power is the power consumed at 100% link load */ - char* idle = bprintf("Invalid idle power value for link%s", this->link->getCname()); - char* busy = bprintf("Invalid busy power value for %s", this->link->getCname()); - - double idleVal = xbt_str_parse_double((current_power_values.at(0)).c_str(), idle); + char* idleMsg = bprintf("Invalid idle power value for link%s", this->link_->get_cname()); + char* busyMsg = bprintf("Invalid busy power value for %s", this->link_->get_cname()); - double busyVal = xbt_str_parse_double((current_power_values.at(1)).c_str(), busy); + idle_ = xbt_str_parse_double((current_power_values.at(0)).c_str(), idleMsg); + busy_ = xbt_str_parse_double((current_power_values.at(1)).c_str(), busyMsg); - this->power_range_watts_list.push_back(LinkPowerRange(idleVal, busyVal)); - - xbt_free(idle); - xbt_free(busy); + xbt_free(idleMsg); + xbt_free(busyMsg); update(); } } @@ -133,26 +121,22 @@ void LinkEnergy::initWattsRangeList() double LinkEnergy::getPower() { - if (power_range_watts_list.empty()) + if (!inited_) return 0.0; - auto range = power_range_watts_list[0]; - - double busy = range.busy; - double idle = range.idle; - - double power_slope = busy - idle; + double power_slope = busy_ - idle_; - double normalized_link_usage = link->getUsage() / link->bandwidth(); + double normalized_link_usage = link_->getUsage() / link_->bandwidth(); double dynamic_power = power_slope * normalized_link_usage; - return idle + dynamic_power; + return idle_ + dynamic_power; } -double LinkEnergy::getTotalEnergy() +double LinkEnergy::getConsumedEnergy() { - update(); - return this->total_energy; + if (lastUpdated_ < surf_get_clock()) // We need to simcall this as it modifies the environment + simgrid::simix::kernelImmediate(std::bind(&LinkEnergy::update, this)); + return this->totalEnergy_; } } } @@ -160,82 +144,40 @@ double LinkEnergy::getTotalEnergy() using simgrid::plugin::LinkEnergy; /* **************************** events callback *************************** */ -static void onCreation(simgrid::s4u::Link& link) -{ - XBT_DEBUG("onCreation is called for link: %s", link.getCname()); - link.extension_set(new LinkEnergy(&link)); -} - -static void onCommunicate(simgrid::surf::NetworkAction* action, simgrid::s4u::Host* src, simgrid::s4u::Host* dst) +static void onCommunicate(simgrid::kernel::resource::NetworkAction* action, simgrid::s4u::Host* src, + simgrid::s4u::Host* dst) { XBT_DEBUG("onCommunicate is called"); - for (simgrid::surf::LinkImpl* link : action->links()) { + for (simgrid::kernel::resource::LinkImpl* link : action->links()) { if (link == nullptr) continue; - XBT_DEBUG("Update link %s", link->getCname()); - // Get the link_energy extension for the relevant link + XBT_DEBUG("Update link %s", link->get_cname()); LinkEnergy* link_energy = link->piface_.extension(); link_energy->initWattsRangeList(); link_energy->update(); } } -static void onActionStateChange(simgrid::surf::NetworkAction* action) -{ - XBT_DEBUG("onActionStateChange is called"); - for (simgrid::surf::LinkImpl* link : action->links()) { - - if (link == nullptr) - continue; - - // Get the link_energy extension for the relevant link - LinkEnergy* link_energy = link->piface_.extension(); - link_energy->update(); - } -} - -static void onLinkStateChange(simgrid::s4u::Link& link) -{ - XBT_DEBUG("onLinkStateChange is called for link: %s", link.getCname()); - - LinkEnergy* link_energy = link.extension(); - link_energy->update(); -} - -static void onLinkDestruction(simgrid::s4u::Link& link) +static void onSimulationEnd() { - XBT_DEBUG("onLinkDestruction is called for link: %s", link.getCname()); - - LinkEnergy* link_energy = link.extension(); - link_energy->update(); -} + std::vector links = simgrid::s4u::Engine::get_instance()->get_all_links(); -static void computeAndDisplayTotalEnergy() -{ - std::vector link_list; - simgrid::s4u::Engine::getInstance()->getLinkList(&link_list); double total_energy = 0.0; // Total dissipated energy (whole platform) - for (const auto link : link_list) { - LinkEnergy* link_energy = link->extension(); - - double a_link_total_energy = link_energy->getTotalEnergy(); - total_energy += a_link_total_energy; - const char* name = link->getCname(); - if (strcmp(name, "__loopback__")) - XBT_INFO("Link '%s' total consumption: %f", name, a_link_total_energy); + for (const auto link : links) { + double link_energy = link->extension()->getConsumedEnergy(); + total_energy += link_energy; } XBT_INFO("Total energy over all links: %f", total_energy); } +/* **************************** Public interface *************************** */ -static void onSimulationEnd() +int sg_link_energy_is_inited() { - computeAndDisplayTotalEnergy(); + return LinkEnergy::EXTENSION_ID.valid(); } -/* **************************** Public interface *************************** */ -SG_BEGIN_DECL() /** \ingroup SURF_plugin_energy * \brief Enable energy plugin * \details Enable energy plugin to get joules consumption of each cpu. You should call this function before @@ -248,12 +190,41 @@ void sg_link_energy_plugin_init() return; LinkEnergy::EXTENSION_ID = simgrid::s4u::Link::extension_create(); - simgrid::s4u::Link::onCreation.connect(&onCreation); - simgrid::s4u::Link::onStateChange.connect(&onLinkStateChange); - simgrid::s4u::Link::onDestruction.connect(&onLinkDestruction); - simgrid::s4u::Link::onCommunicationStateChange.connect(&onActionStateChange); + xbt_assert(sg_host_count() == 0, "Please call sg_link_energy_plugin_init() before initializing the platform."); + + simgrid::s4u::Link::onCreation.connect([](simgrid::s4u::Link& link) { + link.extension_set(new LinkEnergy(&link)); + }); + + simgrid::s4u::Link::onStateChange.connect([](simgrid::s4u::Link& link) { + link.extension()->update(); + }); + + simgrid::s4u::Link::onDestruction.connect([](simgrid::s4u::Link& link) { + if (strcmp(link.get_cname(), "__loopback__")) + XBT_INFO("Energy consumption of link '%s': %f Joules", link.get_cname(), + link.extension()->getConsumedEnergy()); + }); + + simgrid::s4u::Link::onCommunicationStateChange.connect([](simgrid::kernel::resource::NetworkAction* action) { + for (simgrid::kernel::resource::LinkImpl* link : action->links()) { + if (link != nullptr) + link->piface_.extension()->update(); + } + }); + simgrid::s4u::Link::onCommunicate.connect(&onCommunicate); - simgrid::s4u::onSimulationEnd.connect(&onSimulationEnd); + simgrid::s4u::on_simulation_end.connect(&onSimulationEnd); } -SG_END_DECL() +/** @ingroup plugin_energy + * @brief Returns the total energy consumed by the link 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. + */ +double sg_link_get_consumed_energy(sg_link_t link) +{ + return link->extension()->getConsumedEnergy(); +}