Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add new entry in Release_Notes.
[simgrid.git] / docs / source / tuto_network_calibration / dahu_platform_dhist.cpp
1 /* Copyright (c) 2006-2023. 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 "Utils.hpp"
7 #include <boost/property_tree/json_parser.hpp>
8 #include <boost/property_tree/ptree.hpp>
9 #include <map>
10 #include <random>
11 #include <simgrid/s4u.hpp>
12 #include <smpi/smpi.h>
13 namespace sg4 = simgrid::s4u;
14
15 class DhistSampler : public Sampler {
16   bool log_;
17   std::vector<double> breaks_;
18   std::vector<double> heights_;
19   std::mt19937& gen_;
20
21 public:
22   DhistSampler(bool log, std::mt19937& gen, const std::vector<double>& b, const std::vector<double>& h)
23       : log_(log), breaks_(b), heights_(h), gen_(gen)
24   {
25   }
26   double sample() override
27   {
28     std::piecewise_constant_distribution<double> d(breaks_.begin(), breaks_.end(), heights_.begin());
29     auto value = d(gen_);
30     if (log_)
31       value = std::exp(value);
32     return value;
33   }
34 };
35
36 /**
37  * @brief Callback to set latency factor for a communication
38  *
39  * @param latency_base The base latency for this calibration (user-defined)
40  * @param seg Segmentation (user-defined)
41  * @param size Message size (SimGrid)
42  */
43 static double latency_factor_cb(double latency_base, const SegmentedRegression& seg, double size,
44                                 const sg4::Host* /*src*/, const sg4::Host* /*dst*/,
45                                 const std::vector<sg4::Link*>& /*links*/,
46                                 const std::unordered_set<sg4::NetZone*>& /*netzones*/)
47 {
48   if (size < 63305)
49     return 0.0; // no calibration for small messages
50
51   return seg.sample(size) / latency_base;
52 }
53
54 /**
55  * @brief Callback to set bandwidth factor for a communication
56  *
57  * @param bw_base The base bandwidth for this calibration (user-defined)
58  * @param seg Segmentation (user-defined)
59  * @param size Message size (SimGrid)
60  */
61 static double bw_factor_cb(double bw_base, const SegmentedRegression& seg, double size, const sg4::Host* /*src*/,
62                            const sg4::Host* /*dst*/, const std::vector<sg4::Link*>& /*links*/,
63                            const std::unordered_set<sg4::NetZone*>& /*netzones*/)
64 {
65   if (size < 63305)
66     return 1.0; // no calibration for small messages
67   double est_bw = 1.0 / seg.get_coef(size);
68   return est_bw / bw_base;
69 }
70
71 static double smpi_cost_cb(const SegmentedRegression& seg, double size, sg4::Host* /*src*/, sg4::Host* /*dst*/)
72 {
73   return seg.sample(size);
74 }
75
76 /** @brief Auxiliary method to get list of values from json in a vector */
77 static std::vector<double> get_list_from_json(const boost::property_tree::ptree& pt, const std::string& path)
78 {
79   std::vector<double> v;
80   for (const auto& it : pt.get_child(path)) {
81     double value = it.second.get_value<double>();
82     v.push_back(value);
83   }
84   return v;
85 }
86
87 static SegmentedRegression read_json_file(const std::string& jsonFile, std::mt19937& gen, bool read_coef = true)
88 {
89   boost::property_tree::ptree pt;
90   boost::property_tree::read_json(jsonFile, pt);
91
92   printf("Starting parsing file: %s\n", jsonFile.c_str());
93   pt = pt.get_child("seg"); // go to segments part
94   SegmentedRegression seg(read_coef);
95   for (const auto& it : pt) {
96     double max  = it.second.get_child("max_x").get_value<double>();
97     double coef = it.second.get_child("coeff").get_value<double>();
98
99     seg.append(max, coef,
100                std::make_shared<DhistSampler>(it.second.get_child("log").get_value<bool>(), gen,
101                                               get_list_from_json(it.second, "xbr"),
102                                               get_list_from_json(it.second, "height")));
103   }
104   return seg;
105 }
106
107 /** @brief Programmatic version of dahu */
108 extern "C" void load_platform(const sg4::Engine& e);
109 void load_platform(const sg4::Engine& e)
110 {
111   // setting threshold sync/async modes
112   e.set_config("smpi/async-small-thresh", 63305);
113   e.set_config("smpi/send-is-detached-thresh", 63305);
114
115   /* reading bandwidth and latency base value. It is the same for all regressions, get from first file */
116   boost::property_tree::ptree pt;
117   boost::property_tree::read_json("pingpong_dhist.json", pt);
118   double bw_base  = pt.get_child("bandwidth_base").get_value<double>();
119   double lat_base = pt.get_child("latency_base").get_value<double>();
120   printf("Read bandwidth_base: %e latency_base: %e\n", bw_base, lat_base);
121
122   load_dahu_platform(e, bw_base, lat_base);
123
124   static std::mt19937 gen(42); // remove it from stack, since we need it after this this load_platform function is over
125
126   /* setting network factors callbacks */
127   auto* zone              = e.get_netzone_root();
128   SegmentedRegression seg = read_json_file("pingpong_dhist.json", gen, false);
129   zone->set_latency_factor_cb(std::bind(&latency_factor_cb, lat_base, seg, std::placeholders::_1, std::placeholders::_2,
130                                         std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
131
132   zone->set_bandwidth_factor_cb(std::bind(&bw_factor_cb, bw_base, seg, std::placeholders::_1, std::placeholders::_2,
133                                           std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
134
135   seg = read_json_file("send_dhist.json", gen);
136   smpi_register_op_cost_callback(SmpiOperation::SEND, std::bind(&smpi_cost_cb, seg, std::placeholders::_1,
137                                                                 std::placeholders::_2, std::placeholders::_3));
138
139   seg = read_json_file("isend_dhist.json", gen);
140   smpi_register_op_cost_callback(SmpiOperation::ISEND, std::bind(&smpi_cost_cb, seg, std::placeholders::_1,
141                                                                  std::placeholders::_2, std::placeholders::_3));
142   seg = read_json_file("recv_dhist.json", gen);
143   smpi_register_op_cost_callback(SmpiOperation::RECV, std::bind(&smpi_cost_cb, seg, std::placeholders::_1,
144                                                                 std::placeholders::_2, std::placeholders::_3));
145 }