Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Use simgrid::xbt::intrusive_erase().
[simgrid.git] / src / kernel / lmm / fair_bottleneck.cpp
1 /* Copyright (c) 2007-2011, 2013-2017. 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 "src/kernel/lmm/maxmin.hpp"
8 #include "xbt/log.h"
9 #include "xbt/sysdep.h"
10 #include <algorithm>
11 #include <cfloat>
12 #include <cmath>
13 #include <cstdlib>
14 #include <xbt/utility.hpp>
15
16 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(surf_maxmin);
17 #define SHOW_EXPR_G(expr) XBT_DEBUG(#expr " = %g", expr);
18 #define SHOW_EXPR_D(expr) XBT_DEBUG(#expr " = %d", expr);
19 #define SHOW_EXPR_P(expr) XBT_DEBUG(#expr " = %p", expr);
20
21 void simgrid::kernel::lmm::bottleneck_solve(lmm_system_t sys)
22 {
23   if (not sys->modified)
24     return;
25
26   XBT_DEBUG("Variable set : %zu", sys->variable_set.size());
27   for (s_lmm_variable_t& var : sys->variable_set) {
28     var.value = 0.0;
29     XBT_DEBUG("Handling variable %p", &var);
30     if (var.sharing_weight > 0.0 && std::find_if(begin(var.cnsts), end(var.cnsts), [](s_lmm_element_t const& x) {
31                                       return x.consumption_weight != 0.0;
32                                     }) != end(var.cnsts)) {
33       sys->saturated_variable_set.push_back(var);
34     } else {
35       XBT_DEBUG("Err, finally, there is no need to take care of variable %p", &var);
36       if (var.sharing_weight > 0.0)
37         var.value = 1.0;
38     }
39   }
40
41   XBT_DEBUG("Active constraints : %zu", sys->active_constraint_set.size());
42   for (s_lmm_constraint_t& cnst : sys->active_constraint_set) {
43     sys->saturated_constraint_set.push_back(cnst);
44   }
45   for (s_lmm_constraint_t& cnst : sys->saturated_constraint_set) {
46     cnst.remaining = cnst.bound;
47     cnst.usage     = 0.0;
48   }
49
50   XBT_DEBUG("Fair bottleneck Initialized");
51
52   /*
53    * Compute Usage and store the variables that reach the maximum.
54    */
55   auto& var_list  = sys->saturated_variable_set;
56   auto& cnst_list = sys->saturated_constraint_set;
57   do {
58     if (XBT_LOG_ISENABLED(surf_maxmin, xbt_log_priority_debug)) {
59       XBT_DEBUG("Fair bottleneck done");
60       sys->print();
61     }
62     XBT_DEBUG("******* Constraints to process: %zu *******", cnst_list.size());
63     for (auto iter = std::begin(cnst_list); iter != std::end(cnst_list);) {
64       s_lmm_constraint_t& cnst = *iter;
65       int nb = 0;
66       XBT_DEBUG("Processing cnst %p ", &cnst);
67       cnst.usage = 0.0;
68       for (s_lmm_element_t& elem : cnst.enabled_element_set) {
69         xbt_assert(elem.variable->sharing_weight > 0);
70         if (elem.consumption_weight > 0 && elem.variable->saturated_variable_set_hook.is_linked())
71           nb++;
72       }
73       XBT_DEBUG("\tThere are %d variables", nb);
74       if (nb > 0 && not cnst.sharing_policy)
75         nb = 1;
76       if (nb == 0) {
77         cnst.remaining = 0.0;
78         cnst.usage     = 0.0;
79         iter           = cnst_list.erase(iter);
80       } else {
81         cnst.usage = cnst.remaining / nb;
82         XBT_DEBUG("\tConstraint Usage %p : %f with %d variables", &cnst, cnst.usage, nb);
83         iter++;
84       }
85     }
86
87     for (auto iter = std::begin(var_list); iter != std::end(var_list);) {
88       s_lmm_variable_t& var = *iter;
89       double min_inc = DBL_MAX;
90       for (s_lmm_element_t const& elm : var.cnsts) {
91         if (elm.consumption_weight > 0)
92           min_inc = std::min(min_inc, elm.constraint->usage / elm.consumption_weight);
93       }
94       if (var.bound > 0)
95         min_inc = std::min(min_inc, var.bound - var.value);
96       var.mu    = min_inc;
97       XBT_DEBUG("Updating variable %p maximum increment: %g", &var, var.mu);
98       var.value += var.mu;
99       if (var.value == var.bound)
100         iter = var_list.erase(iter);
101       else
102         iter++;
103     }
104
105     for (auto iter = std::begin(cnst_list); iter != std::end(cnst_list);) {
106       s_lmm_constraint_t& cnst = *iter;
107       XBT_DEBUG("Updating cnst %p ", &cnst);
108       if (cnst.sharing_policy) {
109         for (s_lmm_element_t& elem : cnst.enabled_element_set) {
110           xbt_assert(elem.variable->sharing_weight > 0);
111           XBT_DEBUG("\tUpdate constraint %p (%g) with variable %p by %g", &cnst, cnst.remaining, elem.variable,
112                     elem.variable->mu);
113           double_update(&cnst.remaining, elem.consumption_weight * elem.variable->mu, sg_maxmin_precision);
114         }
115       } else {
116         for (s_lmm_element_t& elem : cnst.enabled_element_set) {
117           xbt_assert(elem.variable->sharing_weight > 0);
118           XBT_DEBUG("\tNon-Shared variable. Update constraint usage of %p (%g) with variable %p by %g", &cnst,
119                     cnst.usage, elem.variable, elem.variable->mu);
120           cnst.usage = std::min(cnst.usage, elem.consumption_weight * elem.variable->mu);
121         }
122         XBT_DEBUG("\tUpdate constraint %p (%g) by %g", &cnst, cnst.remaining, cnst.usage);
123         double_update(&cnst.remaining, cnst.usage, sg_maxmin_precision);
124       }
125
126       XBT_DEBUG("\tRemaining for %p : %g", &cnst, cnst.remaining);
127       if (cnst.remaining <= 0.0) {
128         XBT_DEBUG("\tGet rid of constraint %p", &cnst);
129
130         iter = cnst_list.erase(iter);
131         for (s_lmm_element_t& elem : cnst.enabled_element_set) {
132           if (elem.variable->sharing_weight <= 0)
133             break;
134           if (elem.consumption_weight > 0 && elem.variable->saturated_variable_set_hook.is_linked()) {
135             XBT_DEBUG("\t\tGet rid of variable %p", elem.variable);
136             simgrid::xbt::intrusive_erase(var_list, *elem.variable);
137           }
138         }
139       } else {
140         iter++;
141       }
142     }
143   } while (not var_list.empty());
144
145   cnst_list.clear();
146   sys->modified = true;
147   if (XBT_LOG_ISENABLED(surf_maxmin, xbt_log_priority_debug)) {
148     XBT_DEBUG("Fair bottleneck done");
149     sys->print();
150   }
151 }