Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Move FactorSet from smpi::utils to kernel::resource
[simgrid.git] / src / kernel / resource / FactorSet.cpp
1 /* Copyright (c) 2016-2022. The SimGrid Team. All rights reserved.          */
2
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. */
5
6 #include "src/kernel/resource/FactorSet.hpp"
7 #include "xbt/ex.h"
8 #include "xbt/file.hpp"
9 #include "xbt/log.h"
10 #include "xbt/parse_units.hpp"
11 #include "xbt/str.h"
12 #include "xbt/sysdep.h"
13
14 #include <algorithm>
15 //#include <function>
16 #include <boost/tokenizer.hpp>
17
18 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(ker_resource);
19
20 extern std::string surf_parsed_filename;
21 extern int surf_parse_lineno;
22
23 namespace simgrid::kernel::resource {
24
25 void FactorSet::parse(const std::string& values)
26 {
27   const char* str = values.c_str();
28   initialized_    = true;
29
30   if (strchr(str, ':') == nullptr && strchr(str, ';') == nullptr) { // Single value
31     default_value_ = xbt_str_parse_double(str, name_.c_str());
32     return;
33   }
34
35   /** Setup the tokenizer that parses the string **/
36   using Tokenizer = boost::tokenizer<boost::char_separator<char>>;
37   boost::char_separator<char> sep(";");
38   boost::char_separator<char> factor_separator(":");
39   Tokenizer tokens(values, sep);
40
41   /**
42    * Iterate over patterns like A:B:C:D;E:F;G:H
43    * These will be broken down into:
44    * A --> B, C, D
45    * E --> F
46    * G --> H
47    */
48   for (auto token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter) {
49     XBT_DEBUG("token: %s", token_iter->c_str());
50     Tokenizer factor_values(*token_iter, factor_separator);
51     s_smpi_factor_t fact;
52     xbt_assert(factor_values.begin() != factor_values.end(), "Malformed radical for %s: '%s'", name_.c_str(),
53                values.c_str());
54     unsigned int iteration = 0;
55     for (auto factor_iter = factor_values.begin(); factor_iter != factor_values.end(); ++factor_iter) {
56       iteration++;
57
58       if (factor_iter == factor_values.begin()) { /* first element */
59         try {
60           fact.factor = std::stoi(*factor_iter);
61         } catch (const std::invalid_argument&) {
62           throw std::invalid_argument(std::string("Invalid factor in chunk ") + std::to_string(factors_.size() + 1) +
63                                       ": " + *factor_iter + " for " + name_);
64         }
65       } else {
66         try {
67           fact.values.push_back(xbt_parse_get_time(surf_parsed_filename, surf_parse_lineno, *factor_iter, ""));
68         } catch (const std::invalid_argument&) {
69           throw std::invalid_argument(std::string("Invalid factor value ") + std::to_string(iteration) + " in chunk " +
70                                       std::to_string(factors_.size() + 1) + ": " + *factor_iter + " for " + name_);
71         }
72       }
73     }
74
75     factors_.push_back(fact);
76     XBT_DEBUG("smpi_factor:\t%zu: %zu values, first: %f", fact.factor, factors_.size(), fact.values[0]);
77   }
78   std::sort(factors_.begin(), factors_.end(),
79             [](const s_smpi_factor_t& pa, const s_smpi_factor_t& pb) { return (pa.factor < pb.factor); });
80   for (auto const& fact : factors_) {
81     XBT_DEBUG("smpi_factor:\t%zu: %zu values, first: %f", fact.factor, factors_.size(), fact.values[0]);
82   }
83   factors_.shrink_to_fit();
84 }
85
86 FactorSet::FactorSet(const std::string& name, double default_value,
87                      std::function<double(std::vector<double> const&, double)> const& lambda)
88     : name_(name), default_value_(default_value), lambda_(lambda)
89 {
90 }
91
92 double FactorSet::operator()()
93 {
94   return default_value_;
95 }
96
97 double FactorSet::operator()(double size)
98 {
99   if (factors_.empty())
100     return default_value_;
101
102   for (long unsigned i = 0; i < factors_.size(); i++) {
103     auto const& fact = factors_[i];
104
105     if (size <= fact.factor) { // Too large already, use the previous value
106
107       if (i == 0) { // Before the first boundary: use the default value
108         XBT_DEBUG("%s: %f <= %zu return default %f", name_.c_str(), size, fact.factor, default_value_);
109         return default_value_;
110       }
111       double val = lambda_(factors_[i - 1].values, size);
112       XBT_DEBUG("%s: %f <= %zu return %f", name_.c_str(), size, fact.factor, val);
113       return val;
114     }
115   }
116   double val = lambda_(factors_.back().values, size);
117
118   XBT_DEBUG("%s: %f > %zu return %f", name_.c_str(), size, factors_.back().factor, val);
119   return val;
120 }
121 } // namespace simgrid::kernel::resource