Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add some Noteworthy tests to the Contributor's doc
[simgrid.git] / docs / source / tuto_network_calibration / dahu_platform_ckmeans.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 NormalMixture : public Sampler {
16   std::vector<std::normal_distribution<double>> mixture_;
17   std::vector<double> prob_;
18   std::mt19937& gen_;
19
20 public:
21   NormalMixture(std::mt19937& gen) : gen_(gen) {}
22   void append(double mean, double stddev, double prob)
23   {
24     mixture_.push_back(std::normal_distribution<double>(mean, stddev));
25     prob_.push_back(prob);
26   }
27   double sample()
28   {
29     std::discrete_distribution<> d(prob_.begin(), prob_.end());
30     int index    = d(gen_);
31     auto& normal = mixture_[index];
32     double value = normal(gen_);
33     return value;
34   }
35 };
36
37 /**
38  * @brief Callback to set latency factor for a communication
39  *
40  * @param latency_base The base latency for this calibration (user-defined)
41  * @param seg Segmentation (user-defined)
42  * @param size Message size (simgrid)
43  */
44 static double latency_factor_cb(double latency_base, const SegmentedRegression& seg, double size,
45                                 const sg4::Host* /*src*/, const sg4::Host* /*dst*/,
46                                 const std::vector<sg4::Link*>& /*links*/,
47                                 const std::unordered_set<sg4::NetZone*>& /*netzones*/)
48 {
49   if (size < 63305)
50     return 0.0; // no calibration for small messages
51
52   return seg.sample(size) / latency_base;
53 }
54
55 /**
56  * @brief Callback to set bandwidth factor for a communication
57  *
58  * @param bw_base The base bandwidth for this calibration (user-defined)
59  * @param seg Segmentation (user-defined)
60  * @param size Message size (simgrid)
61  */
62 static double bw_factor_cb(double bw_base, const SegmentedRegression& seg, double size, const sg4::Host* /*src*/,
63                            const sg4::Host* /*dst*/, const std::vector<sg4::Link*>& /*links*/,
64                            const std::unordered_set<sg4::NetZone*>& /*netzones*/)
65 {
66   if (size < 63305)
67     return 1.0; // no calibration for small messages
68   double est_bw = 1.0 / seg.get_coef(size);
69   return est_bw / bw_base;
70 }
71
72 static double smpi_cost_cb(const SegmentedRegression& seg, double size, sg4::Host* /*src*/, sg4::Host* /*dst*/)
73 {
74   return seg.sample(size);
75 }
76
77 static SegmentedRegression read_json_file(const std::string& jsonFile, std::mt19937& gen, bool read_coef = true)
78 {
79   boost::property_tree::ptree pt;
80   boost::property_tree::read_json(jsonFile, pt);
81   std::unordered_map<double, std::shared_ptr<NormalMixture>> mixtures;
82   std::unordered_map<double, double> coefs;
83   printf("Starting parsing file: %s\n", jsonFile.c_str());
84   pt = pt.get_child("seg"); // go to segments part
85   SegmentedRegression seg(read_coef);
86   for (const auto& it : pt) {
87     double max    = it.second.get_child("max_x").get_value<double>();
88     coefs[max]    = it.second.get_child("coefficient").get_value<double>();
89     auto& mixture = mixtures[max];
90     if (not mixture)
91       mixture = std::make_shared<NormalMixture>(gen);
92     mixture->append(it.second.get_child("mean").get_value<double>(), it.second.get_child("sd").get_value<double>(),
93                     it.second.get_child("prob").get_value<double>());
94   }
95   for (const auto& i : mixtures) {
96     seg.append(i.first, coefs[i.first], i.second);
97   }
98   return seg;
99 }
100
101 /** @brief Programmatic version of dahu */
102 extern "C" void load_platform(const sg4::Engine& e);
103 void load_platform(const sg4::Engine& e)
104 {
105   // setting threshold sync/async modes
106   e.set_config("smpi/async-small-thresh", 63305);
107   e.set_config("smpi/send-is-detached-thresh", 63305);
108
109   /* reading bandwidth and latency base value. It is the same for all regressions, get from first file */
110   boost::property_tree::ptree pt;
111   boost::property_tree::read_json("pingpong_ckmeans.json", pt);
112   double bw_base  = pt.get_child("bandwidth_base").get_value<double>();
113   double lat_base = pt.get_child("latency_base").get_value<double>();
114   printf("Read bandwidth_base: %e latency_base: %e\n", bw_base, lat_base);
115
116   load_dahu_platform(e, bw_base, lat_base);
117
118   static std::mt19937 gen(42); // remove it from stack, since we need it after this this load_platform function is over
119
120   /* setting network factors callbacks */
121   auto zone = e.get_netzone_root();
122
123   SegmentedRegression seg = read_json_file("pingpong_ckmeans.json", gen, false);
124   zone->set_lat_factor_cb(std::bind(&latency_factor_cb, lat_base, seg, std::placeholders::_1, std::placeholders::_2,
125                                     std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
126
127   zone->set_bw_factor_cb(std::bind(&bw_factor_cb, bw_base, seg, std::placeholders::_1, std::placeholders::_2,
128                                    std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
129
130   seg = read_json_file("send_ckmeans.json", gen);
131   smpi_register_op_cost_callback(SmpiOperation::SEND, std::bind(&smpi_cost_cb, seg, std::placeholders::_1,
132                                                                 std::placeholders::_2, std::placeholders::_3));
133
134   seg = read_json_file("isend_ckmeans.json", gen);
135   smpi_register_op_cost_callback(SmpiOperation::ISEND, std::bind(&smpi_cost_cb, seg, std::placeholders::_1,
136                                                                  std::placeholders::_2, std::placeholders::_3));
137   seg = read_json_file("recv_ckmeans.json", gen);
138   smpi_register_op_cost_callback(SmpiOperation::RECV, std::bind(&smpi_cost_cb, seg, std::placeholders::_1,
139                                                                 std::placeholders::_2, std::placeholders::_3));
140 }