Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
c403d2ba74d46e1f60f8af3210692fa373c95319
[simgrid.git] / examples / cpp / network-nonlinear / s4u-network-nonlinear.cpp
1 /* Copyright (c) 2010-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 /* This example shows how to simulate a non-linear resource sharing for
7  * network links.
8  */
9
10 #include <simgrid/s4u.hpp>
11 #include <string>
12
13 namespace sg4 = simgrid::s4u;
14
15 XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_network_nonlinear, "Messages specific for this s4u example");
16
17 /*************************************************************************************************/
18 class Sender {
19   int messages_count; /* - number of messages */
20   int msg_size = 1e6; /* - message size in bytes */
21
22 public:
23   explicit Sender(int count) : messages_count(count) {}
24   void operator()() const
25   {
26     // sphinx-doc: init-begin (this line helps the doc to build; ignore it)
27     /* ActivitySet in which we store all ongoing communications */
28     sg4::ActivitySet pending_comms;
29
30     /* Mailbox to use */
31     sg4::Mailbox* mbox = sg4::Mailbox::by_name("receiver");
32     // sphinx-doc: init-end
33
34     /* Start dispatching all messages to receiver */
35     for (int i = 0; i < messages_count; i++) {
36       std::string msg_content = "Message " + std::to_string(i);
37       // Copy the data we send: the 'msg_content' variable is not a stable storage location.
38       // It will be destroyed when this actor leaves the loop, ie before the receiver gets it
39       auto* payload           = new std::string(msg_content);
40       unsigned long long size = msg_size * (i + 1);
41       XBT_INFO("Send '%s' to '%s, msg size: %llu'", msg_content.c_str(), mbox->get_cname(), size);
42
43       /* Create a communication representing the ongoing communication, and store it in pending_comms */
44       sg4::CommPtr comm = mbox->put_async(payload, size);
45       pending_comms.push(comm);
46     }
47
48     XBT_INFO("Done dispatching all messages");
49
50     /* Now that all message exchanges were initiated, wait for their completion in one single call */
51     pending_comms.wait_all();
52     // sphinx-doc: put-end
53
54     XBT_INFO("Goodbye now!");
55   }
56 };
57
58 /* Receiver actor expects 1 argument: number of messages to be received */
59 class Receiver {
60   sg4::Mailbox* mbox;
61   int messages_count = 10; /* - number of messages */
62
63 public:
64   explicit Receiver(int count) : messages_count(count) { mbox = sg4::Mailbox::by_name("receiver"); }
65   void operator()()
66   {
67     /* Where we store all incoming msgs */
68     std::unordered_map<sg4::CommPtr, std::shared_ptr<std::string*>> pending_msgs;
69     sg4::ActivitySet pending_comms;
70
71     XBT_INFO("Wait for %d messages asynchronously", messages_count);
72     for (int i = 0; i < messages_count; i++) {
73       std::shared_ptr<std::string*> msg =std::make_shared<std::string*>();
74       auto comm = mbox->get_async<std::string>(msg.get());
75       pending_comms.push(comm);
76       pending_msgs.insert({comm, msg});
77     }
78
79     while (not pending_comms.empty()) {
80       auto completed_one = pending_comms.wait_any();
81       if (completed_one != nullptr){
82         auto comm = boost::dynamic_pointer_cast<sg4::Comm>(completed_one);
83         auto msg = *pending_msgs[comm];
84         XBT_INFO("I got '%s'.", msg->c_str());
85         /* cleanup memory and remove from map */
86         delete msg;
87         pending_msgs.erase(comm);
88       }
89     }
90   }
91 };
92
93 /*************************************************************************************************/
94 /** @brief Non-linear resource sharing for links
95  *
96  * Note that the callback is called twice in this example:
97  * 1) link UP: with the number of active flows (from 9 to 1)
98  * 2) link DOWN: with 0 active flows. A crosstraffic communication is happing
99  * in the down link, but it's not considered as an active flow.
100  */
101 static double link_nonlinear(const sg4::Link* link, double capacity, int n)
102 {
103   /* emulates a degradation in link according to the number of flows
104    * you probably want something more complex than that and based on real
105    * experiments */
106   capacity = std::min(capacity, capacity * (1.0 - (n - 1) / 10.0));
107   XBT_INFO("Link %s, %d active communications, new capacity %lf", link->get_cname(), n, capacity);
108   return capacity;
109 }
110
111 /** @brief Create a simple 2-hosts platform */
112 static void load_platform()
113 {
114   /* Creates the platform
115    *  ________                 __________
116    * | Sender |===============| Receiver |
117    * |________|    Link1      |__________|
118    */
119   auto* zone     = sg4::create_full_zone("Zone1");
120   auto* sender   = zone->create_host("sender", 1)->seal();
121   auto* receiver = zone->create_host("receiver", 1)->seal();
122
123   auto* link = zone->create_split_duplex_link("link1", 1e6);
124   /* setting same callbacks (could be different) for link UP/DOWN in split-duplex link */
125   link->get_link_up()->set_sharing_policy(
126       sg4::Link::SharingPolicy::NONLINEAR,
127       std::bind(&link_nonlinear, link->get_link_up(), std::placeholders::_1, std::placeholders::_2));
128   link->get_link_down()->set_sharing_policy(
129       sg4::Link::SharingPolicy::NONLINEAR,
130       std::bind(&link_nonlinear, link->get_link_down(), std::placeholders::_1, std::placeholders::_2));
131   link->set_latency(10e-6)->seal();
132
133   /* create routes between nodes */
134   zone->add_route(sender->get_netpoint(), receiver->get_netpoint(), nullptr, nullptr,
135                   {{link, sg4::LinkInRoute::Direction::UP}}, true);
136   zone->seal();
137
138   /* create actors Sender/Receiver */
139   sg4::Actor::create("receiver", receiver, Receiver(9));
140   sg4::Actor::create("sender", sender, Sender(9));
141 }
142
143 /*************************************************************************************************/
144 int main(int argc, char* argv[])
145 {
146   sg4::Engine e(&argc, argv);
147
148   /* create platform */
149   load_platform();
150
151   /* runs the simulation */
152   e.run();
153
154   return 0;
155 }