Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add new entry in Release_Notes.
[simgrid.git] / examples / cpp / cloud-capping / s4u-cloud-capping.cpp
1 /* Copyright (c) 2007-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 "simgrid/s4u.hpp"
7 #include "simgrid/plugins/live_migration.h"
8 #include "simgrid/s4u/VirtualMachine.hpp"
9
10 XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_test, "Messages specific for this s4u example");
11 namespace sg4 = simgrid::s4u;
12
13 static void worker(double computation_amount, bool use_bound, double bound)
14 {
15   double clock_start = sg4::Engine::get_clock();
16
17   sg4::ExecPtr exec = sg4::this_actor::exec_init(computation_amount);
18
19   if (use_bound) {
20     if (bound < 1e-12) /* close enough to 0 without any floating precision surprise */
21       XBT_INFO("bound == 0 means no capping (i.e., unlimited).");
22     exec->set_bound(bound);
23   }
24   exec->start();
25   exec->wait();
26   double clock_end     = sg4::Engine::get_clock();
27   double duration      = clock_end - clock_start;
28   double flops_per_sec = computation_amount / duration;
29
30   if (use_bound)
31     XBT_INFO("bound to %f => duration %f (%f flops/s)", bound, duration, flops_per_sec);
32   else
33     XBT_INFO("not bound => duration %f (%f flops/s)", duration, flops_per_sec);
34 }
35
36 static void worker_busy_loop(const char* name, double speed)
37 {
38   double exec_remain_prev    = 1e11;
39   sg4::ExecPtr exec          = sg4::this_actor::exec_async(exec_remain_prev);
40   for (int i = 0; i < 10; i++) {
41     if (speed > 0) {
42       double new_bound = (speed / 10) * i;
43       XBT_INFO("set bound of VM1 to %f", new_bound);
44       static_cast<sg4::VirtualMachine*>(sg4::this_actor::get_host())->set_bound(new_bound);
45     }
46     sg4::this_actor::sleep_for(100);
47     double exec_remain_now = exec->get_remaining();
48     double flops_per_sec   = exec_remain_prev - exec_remain_now;
49     XBT_INFO("%s@%s: %.0f flops/s", name, sg4::this_actor::get_host()->get_cname(), flops_per_sec / 100);
50     exec_remain_prev = exec_remain_now;
51     sg4::this_actor::sleep_for(1);
52   }
53   exec->wait();
54 }
55
56 static void test_dynamic_change()
57 {
58   sg4::Host* pm0 = sg4::Host::by_name("Fafard");
59
60   auto* vm0 = pm0->create_vm("VM0", 1);
61   auto* vm1 = pm0->create_vm("VM1", 1);
62   vm0->start();
63   vm1->start();
64
65   sg4::Actor::create("worker0", vm0, worker_busy_loop, "Task0", -1);
66   sg4::Actor::create("worker1", vm1, worker_busy_loop, "Task1", pm0->get_speed());
67
68   sg4::this_actor::sleep_for(3000); // let the activities end
69   vm0->destroy();
70   vm1->destroy();
71 }
72
73 static void test_one_activity(sg4::Host* host)
74 {
75   const double cpu_speed          = host->get_speed();
76   const double computation_amount = cpu_speed * 10;
77
78   XBT_INFO("### Test: with/without activity set_bound");
79
80   XBT_INFO("### Test: no bound for Task1@%s", host->get_cname());
81   sg4::Actor::create("worker0", host, worker, computation_amount, false, 0);
82
83   sg4::this_actor::sleep_for(1000);
84
85   XBT_INFO("### Test: 50%% for Task1@%s", host->get_cname());
86   sg4::Actor::create("worker0", host, worker, computation_amount, true, cpu_speed / 2);
87
88   sg4::this_actor::sleep_for(1000);
89
90   XBT_INFO("### Test: 33%% for Task1@%s", host->get_cname());
91   sg4::Actor::create("worker0", host, worker, computation_amount, true, cpu_speed / 3);
92
93   sg4::this_actor::sleep_for(1000);
94
95   XBT_INFO("### Test: zero for Task1@%s (i.e., unlimited)", host->get_cname());
96   sg4::Actor::create("worker0", host, worker, computation_amount, true, 0);
97
98   sg4::this_actor::sleep_for(1000);
99
100   XBT_INFO("### Test: 200%% for Task1@%s (i.e., meaningless)", host->get_cname());
101   sg4::Actor::create("worker0", host, worker, computation_amount, true, cpu_speed * 2);
102
103   sg4::this_actor::sleep_for(1000);
104 }
105
106 static void test_two_activities(sg4::Host* hostA, sg4::Host* hostB)
107 {
108   const double cpu_speed = hostA->get_speed();
109   xbt_assert(cpu_speed == hostB->get_speed());
110   const double computation_amount = cpu_speed * 10;
111   const char* hostA_name          = hostA->get_cname();
112   const char* hostB_name          = hostB->get_cname();
113
114   XBT_INFO("### Test: no bound for Task1@%s, no bound for Task2@%s", hostA_name, hostB_name);
115   sg4::Actor::create("worker0", hostA, worker, computation_amount, false, 0);
116   sg4::Actor::create("worker1", hostB, worker, computation_amount, false, 0);
117
118   sg4::this_actor::sleep_for(1000);
119
120   XBT_INFO("### Test: 0 for Task1@%s, 0 for Task2@%s (i.e., unlimited)", hostA_name, hostB_name);
121   sg4::Actor::create("worker0", hostA, worker, computation_amount, true, 0);
122   sg4::Actor::create("worker1", hostB, worker, computation_amount, true, 0);
123
124   sg4::this_actor::sleep_for(1000);
125
126   XBT_INFO("### Test: 50%% for Task1@%s, 50%% for Task2@%s", hostA_name, hostB_name);
127   sg4::Actor::create("worker0", hostA, worker, computation_amount, true, cpu_speed / 2);
128   sg4::Actor::create("worker1", hostB, worker, computation_amount, true, cpu_speed / 2);
129
130   sg4::this_actor::sleep_for(1000);
131
132   XBT_INFO("### Test: 25%% for Task1@%s, 25%% for Task2@%s", hostA_name, hostB_name);
133   sg4::Actor::create("worker0", hostA, worker, computation_amount, true, cpu_speed / 4);
134   sg4::Actor::create("worker1", hostB, worker, computation_amount, true, cpu_speed / 4);
135
136   sg4::this_actor::sleep_for(1000);
137
138   XBT_INFO("### Test: 75%% for Task1@%s, 100%% for Task2@%s", hostA_name, hostB_name);
139   sg4::Actor::create("worker0", hostA, worker, computation_amount, true, cpu_speed * 0.75);
140   sg4::Actor::create("worker1", hostB, worker, computation_amount, true, cpu_speed);
141
142   sg4::this_actor::sleep_for(1000);
143
144   XBT_INFO("### Test: no bound for Task1@%s, 25%% for Task2@%s", hostA_name, hostB_name);
145   sg4::Actor::create("worker0", hostA, worker, computation_amount, false, 0);
146   sg4::Actor::create("worker1", hostB, worker, computation_amount, true, cpu_speed / 4);
147
148   sg4::this_actor::sleep_for(1000);
149
150   XBT_INFO("### Test: 75%% for Task1@%s, 25%% for Task2@%s", hostA_name, hostB_name);
151   sg4::Actor::create("worker0", hostA, worker, computation_amount, true, cpu_speed * 0.75);
152   sg4::Actor::create("worker1", hostB, worker, computation_amount, true, cpu_speed / 4);
153
154   sg4::this_actor::sleep_for(1000);
155 }
156
157 static void master_main()
158 {
159   sg4::Host* pm0 = sg4::Host::by_name("Fafard");
160
161   XBT_INFO("# 1. Put a single activity on a PM.");
162   test_one_activity(pm0);
163   XBT_INFO(".");
164
165   XBT_INFO("# 2. Put two activities on a PM.");
166   test_two_activities(pm0, pm0);
167   XBT_INFO(".");
168
169   auto* vm0 = pm0->create_vm("VM0", 1);
170   vm0->start();
171
172   XBT_INFO("# 3. Put a single activity on a VM.");
173   test_one_activity(vm0);
174   XBT_INFO(".");
175
176   XBT_INFO("# 4. Put two activities on a VM.");
177   test_two_activities(vm0, vm0);
178   XBT_INFO(".");
179
180   vm0->destroy();
181
182   vm0 = pm0->create_vm("VM0", 1);
183   vm0->start();
184
185   XBT_INFO("# 6. Put an activity on a PM and an activity on a VM.");
186   test_two_activities(pm0, vm0);
187   XBT_INFO(".");
188
189   vm0->destroy();
190
191   vm0 = pm0->create_vm("VM0", 1);
192   vm0->set_bound(pm0->get_speed() / 10);
193   vm0->start();
194
195   XBT_INFO("# 7. Put a single activity on the VM capped by 10%%.");
196   test_one_activity(vm0);
197   XBT_INFO(".");
198
199   XBT_INFO("# 8. Put two activities on the VM capped by 10%%.");
200   test_two_activities(vm0, vm0);
201   XBT_INFO(".");
202
203   XBT_INFO("# 9. Put an activity on a PM and an activity on the VM capped by 10%%.");
204   test_two_activities(pm0, vm0);
205   XBT_INFO(".");
206
207   vm0->destroy();
208
209   vm0 = pm0->create_vm("VM0", 1);
210   vm0->set_ramsize(1e9); // 1GB
211   vm0->start();
212
213   double cpu_speed = pm0->get_speed();
214
215   XBT_INFO("# 10. Test migration");
216   const double computation_amount = cpu_speed * 10;
217
218   XBT_INFO("# 10. (a) Put an activity on a VM without any bound.");
219   sg4::Actor::create("worker0", vm0, worker, computation_amount, false, 0);
220   sg4::this_actor::sleep_for(1000);
221   XBT_INFO(".");
222
223   XBT_INFO("# 10. (b) set 10%% bound to the VM, and then put an activity on the VM.");
224   vm0->set_bound(cpu_speed / 10);
225   sg4::Actor::create("worker0", vm0, worker, computation_amount, false, 0);
226   sg4::this_actor::sleep_for(1000);
227   XBT_INFO(".");
228
229   XBT_INFO("# 10. (c) migrate");
230   sg4::Host* pm1 = sg4::Host::by_name("Fafard");
231   sg_vm_migrate(vm0, pm1);
232   XBT_INFO(".");
233
234   XBT_INFO("# 10. (d) Put an activity again on the VM.");
235   sg4::Actor::create("worker0", vm0, worker, computation_amount, false, 0);
236   sg4::this_actor::sleep_for(1000);
237   XBT_INFO(".");
238
239   vm0->destroy();
240
241   XBT_INFO("# 11. Change a bound dynamically.");
242   test_dynamic_change();
243 }
244
245 int main(int argc, char* argv[])
246 {
247   sg4::Engine e(&argc, argv);
248   sg_vm_live_migration_plugin_init();
249   /* load the platform file */
250   xbt_assert(argc == 2, "Usage: %s platform_file\n\tExample: %s ../platforms/small_platform.xml\n", argv[0], argv[0]);
251
252   e.load_platform(argv[1]);
253
254   sg4::Actor::create("master_", e.host_by_name("Fafard"), master_main);
255
256   e.run();
257   XBT_INFO("Bye (simulation time %g)", sg4::Engine::get_clock());
258
259   return 0;
260 }