1 /* Copyright (c) 2004-2017. The SimGrid Team. All rights reserved. */
3 /* This program is free software; you can redistribute it and/or modify it
4 * under the terms of the license (GNU LGPL) which comes with this package. */
6 #ifndef SURF_MAXMIN_PRIVATE_H
7 #define SURF_MAXMIN_PRIVATE_H
9 #include "surf/maxmin.hpp"
10 #include "surf_interface.hpp"
11 #include "xbt/mallocator.h"
18 * Elements can be seen as glue between constraint objects and variable objects.
19 * Basically, each variable will have a set of elements, one for each constraint where it is involved.
20 * Then, it is used to list all variables involved in constraint through constraint's xxx_element_set lists, or
21 * vice-versa list all constraints for a given variable.
23 class s_lmm_element_t {
25 int get_concurrency() const;
26 void decrease_concurrency();
27 void increase_concurrency();
32 /* hookup to constraint */
33 s_xbt_swag_hookup_t enabled_element_set_hookup;
34 s_xbt_swag_hookup_t disabled_element_set_hookup;
35 s_xbt_swag_hookup_t active_element_set_hookup;
37 lmm_constraint_t constraint;
38 lmm_variable_t variable;
40 // consumption_weight: impact of 1 byte or flop of your application onto the resource (in byte or flop)
41 // - if CPU, then probably 1.
42 // - If network, then 1 in forward direction and 0.05 backward for the ACKs
43 double consumption_weight;
46 struct s_lmm_constraint_light_t {
47 double remaining_over_usage;
48 lmm_constraint_t cnst;
52 * @brief LMM constraint
53 * Each constraint contains several partially overlapping logical sets of elements:
54 * \li Disabled elements which variable's weight is zero. This variables are not at all processed by LMM, but eventually the corresponding action will enable it (at least this is the idea).
55 * \li Enabled elements which variable's weight is non-zero. They are utilized in some LMM functions.
56 * \li Active elements which variable's weight is non-zero (i.e. it is enabled) AND its element value is non-zero. LMM_solve iterates over active elements during resolution, dynamically making them active or unactive.
59 class s_lmm_constraint_t {
61 s_lmm_constraint_t() = default;
62 s_lmm_constraint_t(void* id_value, double bound_value);
64 /** @brief Share a constraint. FIXME: name is misleading */
65 void shared() { sharing_policy = 0; }
68 * @brief Check if a constraint is shared (shared by default)
69 * @return 1 if shared, 0 otherwise
71 int get_sharing_policy() const { return sharing_policy; }
74 * @brief Get the usage of the constraint after the last lmm solve
75 * @return The usage of the constraint
77 double get_usage() const;
78 int get_variable_amount() const;
81 * @brief Sets the concurrency limit for this constraint
82 * @param concurrency_limit The concurrency limit to use for this constraint
84 void set_concurrency_limit(int limit)
86 xbt_assert(limit < 0 || concurrency_maximum <= limit,
87 "New concurrency limit should be larger than observed concurrency maximum. Maybe you want to call"
88 " concurrency_maximum_reset() to reset the maximum?");
89 concurrency_limit = limit;
93 * @brief Gets the concurrency limit for this constraint
94 * @return The concurrency limit used by this constraint
96 int get_concurrency_limit() const { return concurrency_limit; }
99 * @brief Reset the concurrency maximum for a given variable (we will update the maximum to reflect constraint
102 void reset_concurrency_maximum() { concurrency_maximum = 0; }
105 * @brief Get the concurrency maximum for a given variable (which reflects constraint evolution).
106 * @return the maximum concurrency of the constraint
108 int get_concurrency_maximum() const
110 xbt_assert(concurrency_limit < 0 || concurrency_maximum <= concurrency_limit,
111 "Very bad: maximum observed concurrency is higher than limit. This is a bug of SURF, please report it.");
112 return concurrency_maximum;
115 int get_concurrency_slack() const
117 return concurrency_limit < 0 ? std::numeric_limits<int>::max() : concurrency_limit - concurrency_current;
121 * @brief Get a var associated to a constraint
122 * @details Get the first variable of the next variable of elem if elem is not NULL
123 * @param elem A element of constraint of the constraint or NULL
124 * @return A variable associated to a constraint
126 lmm_variable_t get_variable(lmm_element_t* elem) const;
129 * @brief Get a var associated to a constraint
130 * @details Get the first variable of the next variable of elem if elem is not NULL
131 * @param elem A element of constraint of the constraint or NULL
132 * @param nextelem A element of constraint of the constraint or NULL, the one after elem
133 * @param numelem parameter representing the number of elements to go
134 * @return A variable associated to a constraint
136 lmm_variable_t get_variable_safe(lmm_element_t* elem, lmm_element_t* nextelem, int* numelem) const;
139 * @brief Get the data associated to a constraint
140 * @return The data associated to the constraint
142 void* get_id() const { return id; }
144 /* hookup to system */
145 s_xbt_swag_hookup_t constraint_set_hookup = {nullptr, nullptr};
146 s_xbt_swag_hookup_t active_constraint_set_hookup = {nullptr, nullptr};
147 s_xbt_swag_hookup_t modified_constraint_set_hookup = {nullptr, nullptr};
148 s_xbt_swag_hookup_t saturated_constraint_set_hookup = {nullptr, nullptr};
149 s_xbt_swag_t enabled_element_set; /* a list of lmm_element_t */
150 s_xbt_swag_t disabled_element_set; /* a list of lmm_element_t */
151 s_xbt_swag_t active_element_set; /* a list of lmm_element_t */
155 //TODO MARTIN Check maximum value across resources at the end of simulation and give a warning is more than e.g. 500
156 int concurrency_current; /* The current concurrency */
157 int concurrency_maximum; /* The maximum number of (enabled and disabled) variables associated to the constraint at any given time (essentially for tracing)*/
159 int sharing_policy; /* see @e_surf_link_sharing_policy_t (0: FATPIPE, 1: SHARED, 2: FULLDUPLEX) */
163 lmm_constraint_light_t cnst_light;
166 static int Global_debug_id;
167 int concurrency_limit; /* The maximum number of variables that may be enabled at any time (stage variables if
172 /** @ingroup SURF_lmm
173 * @brief LMM variable
175 * When something prevents us from enabling a variable, we "stage" the weight that we would have like to set, so that as soon as possible we enable the variable with desired weight
177 class s_lmm_variable_t {
179 void initialize(simgrid::surf::Action* id_value, double sharing_weight_value, double bound_value,
180 int number_of_constraints, unsigned visited_value);
183 * @brief Get the value of the variable after the last lmm solve
184 * @return The value of the variable
186 double get_value() const { return value; }
189 * @brief Get the maximum value of the variable (-1.0 if no maximum value)
190 * @return The bound of the variable
192 double get_bound() const { return bound; }
195 * @brief Set the concurrent share of the variable
196 * @param concurrency_share The new concurrency share
198 void set_concurrency_share(short int value) { concurrency_share = value; }
201 * @brief Get the numth constraint associated to the variable
202 * @param num The rank of constraint we want to get
203 * @return The numth constraint
205 lmm_constraint_t get_constraint(unsigned num) const { return num < cnsts.size() ? cnsts[num].constraint : nullptr; }
208 * @brief Get the weigth of the numth constraint associated to the variable
209 * @param num The rank of constraint we want to get
210 * @return The numth constraint
212 double get_constraint_weight(unsigned num) const { return num < cnsts.size() ? cnsts[num].consumption_weight : 0.0; }
215 * @brief Get the number of constraint associated to a variable
216 * @return The number of constraint associated to the variable
218 int get_number_of_constraint() const { return cnsts.size(); }
221 * @brief Get the data associated to a variable
222 * @return The data associated to the variable
224 simgrid::surf::Action* get_id() const { return id; }
227 * @brief Get the weight of a variable
228 * @return The weight of the variable
230 double get_weight() const { return sharing_weight; }
232 /** @brief Measure the minimum concurrency slack across all constraints where the given var is involved */
233 int get_min_concurrency_slack() const;
235 /** @brief Check if a variable can be enabled
236 * Make sure to set staged_weight before, if your intent is only to check concurrency
238 int can_enable() const { return staged_weight > 0 && get_min_concurrency_slack() >= concurrency_share; }
240 /* hookup to system */
241 s_xbt_swag_hookup_t variable_set_hookup;
242 s_xbt_swag_hookup_t saturated_variable_set_hookup;
244 std::vector<s_lmm_element_t> cnsts;
246 // sharing_weight: variable's impact on the resource during the sharing
247 // if == 0, the variable is not considered by LMM
248 // on CPU, actions with N threads have a sharing of N
249 // on network, the actions with higher latency have a lesser sharing_weight
250 double sharing_weight;
252 double staged_weight; /* If non-zero, variable is staged for addition as soon as maxconcurrency constraints will be met */
255 short int concurrency_share; /* The maximum number of elements that variable will add to a constraint */
256 simgrid::surf::Action* id;
258 unsigned visited; /* used by lmm_update_modified_set */
259 /* \begin{For Lagrange only} */
262 double (*func_f)(s_lmm_variable_t* var, double x); /* (f) */
263 double (*func_fp)(s_lmm_variable_t* var, double x); /* (f') */
264 double (*func_fpi)(s_lmm_variable_t* var, double x); /* (f')^{-1} */
265 /* \end{For Lagrange only} */
268 static int Global_debug_id;
271 inline void s_lmm_element_t::make_active()
273 xbt_swag_insert_at_head(this, &constraint->active_element_set);
275 inline void s_lmm_element_t::make_inactive()
277 xbt_swag_remove(this, &constraint->active_element_set);
280 /** @ingroup SURF_lmm
283 class s_lmm_system_t {
286 * @brief Create a new Linear MaxMim system
287 * @param selective_update whether we should do lazy updates
289 s_lmm_system_t(bool selective_update);
290 /** @brief Free an existing Linear MaxMin system */
294 * @brief Create a new Linear MaxMin constraint
295 * @param id Data associated to the constraint (e.g.: a network link)
296 * @param bound_value The bound value of the constraint
298 lmm_constraint_t constraint_new(void* id, double bound_value);
301 * @brief Create a new Linear MaxMin variable
302 * @param id Data associated to the variable (e.g.: a network communication)
303 * @param weight_value The weight of the variable (0.0 if not used)
304 * @param bound The maximum value of the variable (-1.0 if no maximum value)
305 * @param number_of_constraints The maximum number of constraint to associate to the variable
307 lmm_variable_t variable_new(simgrid::surf::Action* id, double weight_value, double bound, int number_of_constraints);
310 * @brief Free a variable
311 * @param var The variable to free
313 void variable_free(lmm_variable_t var);
316 * @brief Associate a variable to a constraint with a coefficient
317 * @param cnst A constraint
318 * @param var A variable
319 * @param value The coefficient associated to the variable in the constraint
321 void expand(lmm_constraint_t cnst, lmm_variable_t var, double value);
324 * @brief Add value to the coefficient between a constraint and a variable or create one
325 * @param cnst A constraint
326 * @param var A variable
327 * @param value The value to add to the coefficient associated to the variable in the constraint
329 void expand_add(lmm_constraint_t cnst, lmm_variable_t var, double value);
332 * @brief Update the bound of a variable
333 * @param var A constraint
334 * @param bound The new bound
336 void update_variable_bound(lmm_variable_t var, double bound);
339 * @brief Update the weight of a variable
340 * @param var A variable
341 * @param weight The new weight of the variable
343 void update_variable_weight(lmm_variable_t var, double weight);
346 * @brief Update a constraint bound
347 * @param cnst A constraint
348 * @param bound The new bound of the consrtaint
350 void update_constraint_bound(lmm_constraint_t cnst, double bound);
353 * @brief [brief description]
354 * @param cnst A constraint
355 * @return [description]
357 int constraint_used(lmm_constraint_t cnst) { return xbt_swag_belongs(cnst, &active_constraint_set); }
359 /** @brief Print the lmm system */
362 /** @brief Solve the lmm system */
366 static void* variable_mallocator_new_f();
367 static void variable_mallocator_free_f(void* var);
369 void var_free(lmm_variable_t var);
370 void cnst_free(lmm_constraint_t cnst);
371 lmm_variable_t extract_variable() { return static_cast<lmm_variable_t>(xbt_swag_extract(&variable_set)); }
372 lmm_constraint_t extract_constraint() { return static_cast<lmm_constraint_t>(xbt_swag_extract(&constraint_set)); }
373 void insert_constraint(lmm_constraint_t cnst) { xbt_swag_insert(cnst, &constraint_set); }
374 void remove_variable(lmm_variable_t var)
376 xbt_swag_remove(var, &variable_set);
377 xbt_swag_remove(var, &saturated_variable_set);
379 void remove_constraint(lmm_constraint_t cnst) // FIXME: unused
381 xbt_swag_remove(cnst, &constraint_set);
382 xbt_swag_remove(cnst, &saturated_constraint_set);
384 void make_constraint_active(lmm_constraint_t cnst) { xbt_swag_insert(cnst, &active_constraint_set); }
385 void make_constraint_inactive(lmm_constraint_t cnst)
387 xbt_swag_remove(cnst, &active_constraint_set);
388 xbt_swag_remove(cnst, &modified_constraint_set);
391 void enable_var(lmm_variable_t var);
392 void disable_var(lmm_variable_t var);
393 void on_disabled_var(lmm_constraint_t cnstr);
396 * @brief Update the value of element linking the constraint and the variable
397 * @param cnst A constraint
398 * @param var A variable
399 * @param value The new value
401 void update(lmm_constraint_t cnst, lmm_variable_t var, double value);
403 void update_modified_set(lmm_constraint_t cnst);
404 void update_modified_set_rec(lmm_constraint_t cnst);
406 /** @brief Remove all constraints of the modified_constraint_set. */
407 void remove_all_modified_set();
408 void check_concurrency();
412 s_xbt_swag_t variable_set; /* a list of lmm_variable_t */
413 s_xbt_swag_t active_constraint_set; /* a list of lmm_constraint_t */
414 s_xbt_swag_t saturated_variable_set; /* a list of lmm_variable_t */
415 s_xbt_swag_t saturated_constraint_set; /* a list of lmm_constraint_t_t */
417 simgrid::surf::ActionLmmListPtr keep_track;
419 void (*solve_fun)(lmm_system_t self);
422 bool selective_update_active; /* flag to update partially the system only selecting changed portions */
423 unsigned visited_counter; /* used by lmm_update_modified_set and lmm_remove_modified_set to cleverly (un-)flag the
424 * constraints (more details in these functions) */
425 s_xbt_swag_t constraint_set; /* a list of lmm_constraint_t */
426 s_xbt_swag_t modified_constraint_set; /* a list of modified lmm_constraint_t */
427 xbt_mallocator_t variable_mallocator;
430 extern XBT_PRIVATE double (*func_f_def) (lmm_variable_t, double);
431 extern XBT_PRIVATE double (*func_fp_def) (lmm_variable_t, double);
432 extern XBT_PRIVATE double (*func_fpi_def) (lmm_variable_t, double);
434 #endif /* SURF_MAXMIN_PRIVATE_H */