Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
0e2d09d53625adc52b001415cf1e72e9ffe9c80b
[simgrid.git] / examples / cpp / network-factors / s4u-network-factors.cpp
1 /* Copyright (c) 2010-2021. 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 /* This example shows how to build set customized communication factors
7  *
8  * It uses the interface provided by NetworkModelIntf to register 2 callbacks that
9  * are called everytime a communication occurs.
10  *
11  * These factors are used to change the communication time depending on the message size
12  * and destination.
13  *
14  * This example uses factors obtained by some experiments on dahu cluster in Grid'5000.
15  * You must change the values according to the calibration of your enviroment.
16  */
17
18 #include <map>
19 #include <simgrid/kernel/resource/NetworkModelIntf.hpp>
20 #include <simgrid/s4u.hpp>
21 namespace sg4 = simgrid::s4u;
22
23 XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_network_factors, "Messages specific for this s4u example");
24
25 /* Factors used in this platform, for remote and local communications
26  * Obtained from dahu cluster. Obs.: just an example, change the values according
27  * to the calibration on your environment */
28 static const std::map<double, double> REMOTE_BW_FACTOR = {
29     {0, 1.0000000000000002},         {8000, 1.0000000000000002},     {15798, 0.07435006650635523},
30     {64000, 0.3163352696348148},     {6000000, 0.13003278960133288}, {42672591, 0.10354740223279707},
31     {160097505, 0.40258935729656503}};
32 static const std::map<double, double> LOCAL_BW_FACTOR = {{0, 0.17591906192813994},
33                                                          {16000, 0.12119203247138953},
34                                                          {6000000, 0.07551057012803415},
35                                                          {36900419, 0.04281516758309203},
36                                                          {160097505, 0.17440518795992602}};
37
38 static const std::map<double, double> REMOTE_LAT_FACTOR = {{0, 0.0},
39                                                            {8000, 1731.7102918851567},
40                                                            {15798, 1441.073993161278},
41                                                            {64000, 1761.4784830658123},
42                                                            {6000000, 0.0},
43                                                            {42672591, 0.0},
44                                                            {160097505, 970913.4558162984}};
45 static const std::map<double, double> LOCAL_LAT_FACTOR  = {
46     {0, 0.0}, {16000, 650.2212383180362}, {6000000, 0.0}, {36900419, 0.0}, {160097505, 1017885.3518765072}};
47
48 /* bandwidth and latency used on the platform */
49 constexpr static double BW_REMOTE = 12.5e9;
50 constexpr static double BW_LOCAL  = 25e9;
51 constexpr static double LATENCY   = .1e-6;
52
53 /*************************************************************************************************/
54 /** @brief Create a simple platform based on Dahu cluster */
55 static void load_platform()
56 {
57   /**
58    * Inspired on dahu cluster on Grenoble
59    *     ________________
60    *     |               |
61    *     |     dahu      |
62    *     |_______________|
63    *     / /   | |    \ \
64    *    / /    | |     \ \     <-- 12.5GBps links
65    *   / /     | |      \ \
66    * host1     ...      hostN
67    */
68
69   auto* root         = sg4::create_star_zone("dahu");
70   std::string prefix = "dahu-";
71   std::string suffix = ".grid5000.fr";
72
73   for (int id = 0; id < 32; id++) {
74     std::string hostname = prefix + std::to_string(id) + suffix;
75     /* create host */
76     const sg4::Host* host = root->create_host(hostname, 1)->set_core_count(32)->seal();
77     /* create UP/DOWN link */
78     sg4::Link* l_up   = root->create_link(hostname + "_up", BW_REMOTE)->set_latency(LATENCY)->seal();
79     sg4::Link* l_down = root->create_link(hostname + "_down", BW_REMOTE)->set_latency(LATENCY)->seal();
80
81     /* add link UP/DOWN for communications from the host */
82     root->add_route(host->get_netpoint(), nullptr, nullptr, nullptr, std::vector<sg4::Link*>{l_up}, false);
83     root->add_route(nullptr, host->get_netpoint(), nullptr, nullptr, std::vector<sg4::Link*>{l_down}, false);
84
85     sg4::Link* loopback = root->create_link(hostname + "_loopback", BW_LOCAL)->set_latency(LATENCY)->seal();
86     root->add_route(host->get_netpoint(), host->get_netpoint(), nullptr, nullptr, std::vector<sg4::Link*>{loopback});
87   }
88
89   root->seal();
90 }
91
92 /*************************************************************************************************/
93 /** @brief Auxiliary method to get factor for a message size */
94 static double get_factor_from_map(const std::map<double, double>& factors, double size)
95 {
96   double factor = 1.0;
97   for (auto const& fact : factors) {
98     if (size < fact.first) {
99       break;
100     } else {
101       factor = fact.second;
102     }
103   }
104   return factor;
105 }
106
107 /**
108  * @brief Callback to set latency factor for a communication
109  *
110  * Set different factors for local (loopback) and remote communications.
111  * Function signature is defined by API
112  *
113  * @param size Message size
114  * @param src Host origin
115  * @param dst Host destination
116  */
117 static double latency_factor_cb(double size, const sg4::Host* src, const sg4::Host* dst,
118                                 const std::vector<sg4::Link*>& /*links*/,
119                                 const std::unordered_set<sg4::NetZone*>& /*netzones*/)
120 {
121   if (src->get_name() == dst->get_name()) {
122     /* local communication factors */
123     return get_factor_from_map(LOCAL_LAT_FACTOR, size);
124   } else {
125     return get_factor_from_map(REMOTE_LAT_FACTOR, size);
126   }
127 }
128
129 /**
130  * @brief Callback to set bandwidth factor for a communication
131  *
132  * Set different factors for local (loopback) and remote communications.
133  * Function signature is defined by API
134  *
135  * @param size Message size
136  * @param src Host origin
137  * @param dst Host destination
138  */
139 static double bandwidth_factor_cb(double size, const sg4::Host* src, const sg4::Host* dst,
140                                   const std::vector<sg4::Link*>& /*links*/,
141                                   const std::unordered_set<sg4::NetZone*>& /*netzones*/)
142 {
143   if (src->get_name() == dst->get_name()) {
144     /* local communication factors */
145     return get_factor_from_map(LOCAL_BW_FACTOR, size);
146   } else {
147     return get_factor_from_map(REMOTE_BW_FACTOR, size);
148   }
149 }
150
151 /*************************************************************************************************/
152 class Sender {
153   std::vector<sg4::Host*> hosts_;
154   double crosstraffic_ = 1.0;
155
156 public:
157   explicit Sender(const std::vector<sg4::Host*>& hosts, bool crosstraffic) : hosts_{hosts}
158   {
159     if (crosstraffic)
160       crosstraffic_ = 1.05; // add crosstraffic load if it is enabled
161   }
162   void operator()() const
163   {
164     const std::vector<double> msg_sizes = {64e3, 64e6, 64e9}; // 64KB, 64MB, 64GB
165
166     for (double size : msg_sizes) {
167       for (const auto* host : hosts_) {
168         std::string msg;
169         /* calculating the estimated communication time depending of message size and destination */
170         if (host->get_name() == sg4::this_actor::get_host()->get_name()) {
171           double lat_factor = get_factor_from_map(LOCAL_LAT_FACTOR, size);
172           double bw_factor  = get_factor_from_map(LOCAL_BW_FACTOR, size);
173           /* Account for crosstraffic on local communications
174            * local communications use only a single link and crosstraffic impact on resource sharing
175            * on remote communications, we don't see this effect since we have split-duplex links */
176           double est_time =
177               sg4::Engine::get_clock() + size / (BW_LOCAL * bw_factor / crosstraffic_) + LATENCY * lat_factor;
178
179           msg = "Local communication: size=" + std::to_string(size) + ". Use bw_factor=" + std::to_string(bw_factor) +
180                 " lat_factor=" + std::to_string(lat_factor) + ". Estimated finished time=" + std::to_string(est_time);
181         } else {
182           double lat_factor = get_factor_from_map(REMOTE_LAT_FACTOR, size);
183           double bw_factor  = get_factor_from_map(REMOTE_BW_FACTOR, size);
184           double est_time   = sg4::Engine::get_clock() + (size / (BW_REMOTE * bw_factor)) + LATENCY * lat_factor * 2;
185           msg = "Remote communication: size=" + std::to_string(size) + ". Use bw_factor=" + std::to_string(bw_factor) +
186                 " lat_factor=" + std::to_string(lat_factor) + ". Estimated finished time=" + std::to_string(est_time);
187         }
188
189         /* Create a communication representing the ongoing communication */
190         auto mbox     = sg4::Mailbox::by_name(host->get_name());
191         auto* payload = new std::string(msg);
192         mbox->put(payload, static_cast<uint64_t>(size));
193       }
194     }
195
196     XBT_INFO("Done dispatching all messages");
197     /* sending message to stop receivers */
198     for (const auto* host : hosts_) {
199       auto mbox = sg4::Mailbox::by_name(host->get_name());
200       mbox->put(new std::string("finalize"), 0);
201     }
202   }
203 };
204
205 /* Receiver actor: wait for messages on the mailbox identified by the hostname */
206 class Receiver {
207 public:
208   void operator()() const
209   {
210     auto mbox = sg4::Mailbox::by_name(sg4::this_actor::get_host()->get_name());
211     // Receiving the message was all we were supposed to do
212     for (bool cont = true; cont;) {
213       auto received = mbox->get_unique<std::string>();
214       XBT_INFO("I got a '%s'.", received->c_str());
215       cont = (*received != "finalize"); // If it's a finalize message, we're done
216     }
217   }
218 };
219
220 /*************************************************************************************************/
221 int main(int argc, char* argv[])
222 {
223   bool crosstraffic = true;
224   sg4::Engine e(&argc, argv);
225   /* setting network model to default one */
226   sg4::Engine::set_config("network/model:CM02");
227
228   /* test with crosstraffic disabled */
229   if (argc == 2 && std::string(argv[1]) == "disable_crosstraffic") {
230     sg4::Engine::set_config("network/crosstraffic:0");
231     crosstraffic = false;
232   }
233
234   /* create platform */
235   load_platform();
236   /* setting network factors callbacks */
237   simgrid::kernel::resource::NetworkModelIntf* model = e.get_netzone_root()->get_network_model();
238   model->set_lat_factor_cb(latency_factor_cb);
239   model->set_bw_factor_cb(bandwidth_factor_cb);
240
241   sg4::Host* host        = e.host_by_name("dahu-1.grid5000.fr");
242   sg4::Host* host_remote = e.host_by_name("dahu-10.grid5000.fr");
243   sg4::Actor::create(std::string("receiver-local"), host, Receiver());
244   sg4::Actor::create(std::string("receiver-remote"), host_remote, Receiver());
245   sg4::Actor::create(std::string("sender") + std::string(host->get_name()), host,
246                      Sender({host, host_remote}, crosstraffic));
247
248   /* runs the simulation */
249   e.run();
250
251   return 0;
252 }