Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Remove useless length modifier 'l' in %l[efg] for printf.
[simgrid.git] / examples / msg / cloud / bound.c
1 /* Copyright (c) 2007-2014. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include <stdio.h>
8 #include "msg/msg.h"            /* Yeah! If you want to use msg, you need to include msg/msg.h */
9 #include "xbt/sysdep.h"         /* calloc, printf */
10
11 /* Create a log channel to have nice outputs. */
12 #include "xbt/log.h"
13 #include "xbt/asserts.h"
14 XBT_LOG_NEW_DEFAULT_CATEGORY(msg_test,
15                              "Messages specific for this msg example");
16
17 /** @addtogroup MSG_examples
18  *
19  * - <b>priority/priority.c</b>: Demonstrates the use of @ref
20  *   MSG_task_set_bound to change the computation priority of a
21  *   given task.
22  *
23  */
24
25 static int worker_main(int argc, char *argv[])
26 {
27   double computation_amount = atof(argv[1]);
28   int use_bound = atoi(argv[2]);
29   double bound = atof(argv[3]);
30
31   {
32     double clock_sta = MSG_get_clock();
33
34     msg_task_t task = MSG_task_create("Task", computation_amount, 0, NULL);
35     if (use_bound)
36       MSG_task_set_bound(task, bound);
37     MSG_task_execute(task);
38     MSG_task_destroy(task);
39
40     double clock_end = MSG_get_clock();
41     double duration = clock_end - clock_sta;
42     double flops_per_sec = computation_amount / duration;
43
44     if (use_bound)
45       XBT_INFO("bound to %f => duration %f (%f flops/s)", bound, duration, flops_per_sec);
46     else
47       XBT_INFO("not bound => duration %f (%f flops/s)", duration, flops_per_sec);
48   }
49
50   return 0;
51 }
52
53 static void launch_worker(msg_host_t host, const char *pr_name, double computation_amount, int use_bound, double bound)
54 {
55   char **argv = xbt_new(char *, 5);
56   argv[0] = xbt_strdup(pr_name);
57   argv[1] = bprintf("%f", computation_amount);
58   argv[2] = bprintf("%d", use_bound);
59   argv[3] = bprintf("%f", bound);
60   argv[4] = NULL;
61
62   MSG_process_create_with_arguments(pr_name, worker_main, NULL, host, 4, argv);
63 }
64
65
66
67 static int worker_busy_loop_main(int argc, char *argv[])
68 {
69   msg_task_t *task = MSG_process_get_data(MSG_process_self());
70   for (;;)
71     MSG_task_execute(*task);
72
73   return 0;
74 }
75
76 /* FIXME: */
77 #define DOUBLE_MAX 1e11
78
79 static void test_dynamic_change(void)
80 {
81   xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar();
82   msg_host_t pm0 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t);
83
84   msg_host_t vm0 = MSG_vm_create_core(pm0, "VM0");
85   msg_host_t vm1 = MSG_vm_create_core(pm0, "VM1");
86   MSG_vm_start(vm0);
87   MSG_vm_start(vm1);
88
89   msg_task_t task0 = MSG_task_create("Task0", DOUBLE_MAX, 0, NULL);
90   msg_task_t task1 = MSG_task_create("Task1", DOUBLE_MAX, 0, NULL);
91   msg_process_t pr0 = MSG_process_create("worker0", worker_busy_loop_main, &task0, vm0);
92   msg_process_t pr1 = MSG_process_create("worker1", worker_busy_loop_main, &task1, vm1);
93
94
95   double task0_remain_prev = MSG_task_get_remaining_computation(task0);
96   double task1_remain_prev = MSG_task_get_remaining_computation(task1);
97
98   {
99     const double cpu_speed = MSG_get_host_speed(pm0);
100     int i = 0;
101     for (i = 0; i < 10; i++) {
102       double new_bound = (cpu_speed / 10) * i;
103       XBT_INFO("set bound of VM1 to %f", new_bound);
104       MSG_vm_set_bound(vm1, new_bound);
105       MSG_process_sleep(100);
106
107       double task0_remain_now = MSG_task_get_remaining_computation(task0);
108       double task1_remain_now = MSG_task_get_remaining_computation(task1);
109
110       double task0_flops_per_sec = task0_remain_prev - task0_remain_now;
111       double task1_flops_per_sec = task1_remain_prev - task1_remain_now;
112
113       XBT_INFO("Task0@VM0: %f flops/s", task0_flops_per_sec / 100);
114       XBT_INFO("Task1@VM1: %f flops/s", task1_flops_per_sec / 100);
115
116       task0_remain_prev = task0_remain_now;
117       task1_remain_prev = task1_remain_now;
118     }
119   }
120
121   MSG_process_kill(pr0);
122   MSG_process_kill(pr1);
123   
124   MSG_vm_destroy(vm0);
125   MSG_vm_destroy(vm1);
126 }
127
128
129
130 static void test_one_task(msg_host_t hostA)
131 {
132   const double cpu_speed = MSG_get_host_speed(hostA);
133   const double computation_amount = cpu_speed * 10;
134   const char *hostA_name = MSG_host_get_name(hostA);
135
136   XBT_INFO("### Test: with/without MSG_task_set_bound");
137
138 #if 0
139   /* Easy-to-understand code (without calling MSG_task_set_bound) */
140   {
141     double clock_sta = MSG_get_clock();
142
143     msg_task_t task = MSG_task_create("Task", computation_amount, 0, NULL);
144     MSG_task_execute(task);
145     MSG_task_destroy(task);
146
147     double clock_end = MSG_get_clock();
148     double duration = clock_end - clock_sta;
149     double flops_per_sec = computation_amount / duration;
150
151     XBT_INFO("not bound => duration %f (%f flops/s)", duration, flops_per_sec);
152   }
153
154   /* Easy-to-understand code (with calling MSG_task_set_bound) */
155   {
156     double clock_sta = MSG_get_clock();
157
158     msg_task_t task = MSG_task_create("Task", computation_amount, 0, NULL);
159     MSG_task_set_bound(task, cpu_speed / 2);
160     MSG_task_execute(task);
161     MSG_task_destroy(task);
162
163     double clock_end = MSG_get_clock();
164     double duration = clock_end - clock_sta;
165     double flops_per_sec = computation_amount / duration;
166
167     XBT_INFO("bound to 0.5 => duration %f (%f flops/s)", duration, flops_per_sec);
168   }
169 #endif
170
171   {
172     XBT_INFO("### Test: no bound for Task1@%s", hostA_name);
173     launch_worker(hostA, "worker0", computation_amount, 0, 0);
174   }
175
176   MSG_process_sleep(1000);
177
178   {
179     XBT_INFO("### Test: 50%% for Task1@%s", hostA_name);
180     launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed / 2);
181   }
182
183   MSG_process_sleep(1000);
184
185   {
186     XBT_INFO("### Test: 33%% for Task1@%s", hostA_name);
187     launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed / 3);
188   }
189
190   MSG_process_sleep(1000);
191
192   {
193     XBT_INFO("### Test: zero for Task1@%s (i.e., unlimited)", hostA_name);
194     launch_worker(hostA, "worker0", computation_amount, 1, 0);
195   }
196
197   MSG_process_sleep(1000);
198
199   {
200     XBT_INFO("### Test: 200%% for Task1@%s (i.e., meaningless)", hostA_name);
201     launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed * 2);
202   }
203
204   MSG_process_sleep(1000);
205 }
206
207
208 static void test_two_tasks(msg_host_t hostA, msg_host_t hostB)
209 {
210   const double cpu_speed = MSG_get_host_speed(hostA);
211   xbt_assert(cpu_speed == MSG_get_host_speed(hostB));
212   const double computation_amount = cpu_speed * 10;
213   const char *hostA_name = MSG_host_get_name(hostA);
214   const char *hostB_name = MSG_host_get_name(hostB);
215
216   {
217     XBT_INFO("### Test: no bound for Task1@%s, no bound for Task2@%s", hostA_name, hostB_name);
218     launch_worker(hostA, "worker0", computation_amount, 0, 0);
219     launch_worker(hostB, "worker1", computation_amount, 0, 0);
220   }
221
222   MSG_process_sleep(1000);
223
224   {
225     XBT_INFO("### Test: 0 for Task1@%s, 0 for Task2@%s (i.e., unlimited)", hostA_name, hostB_name);
226     launch_worker(hostA, "worker0", computation_amount, 1, 0);
227     launch_worker(hostB, "worker1", computation_amount, 1, 0);
228   }
229
230   MSG_process_sleep(1000);
231
232   {
233     XBT_INFO("### Test: 50%% for Task1@%s, 50%% for Task2@%s", hostA_name, hostB_name);
234     launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed / 2);
235     launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed / 2);
236   }
237
238   MSG_process_sleep(1000);
239
240   {
241     XBT_INFO("### Test: 25%% for Task1@%s, 25%% for Task2@%s", hostA_name, hostB_name);
242     launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed / 4);
243     launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed / 4);
244   }
245
246   MSG_process_sleep(1000);
247
248   {
249     XBT_INFO("### Test: 75%% for Task1@%s, 100%% for Task2@%s", hostA_name, hostB_name);
250     launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed * 0.75);
251     launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed);
252   }
253
254   MSG_process_sleep(1000);
255
256   {
257     XBT_INFO("### Test: no bound for Task1@%s, 25%% for Task2@%s", hostA_name, hostB_name);
258     launch_worker(hostA, "worker0", computation_amount, 0, 0);
259     launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed / 4);
260   }
261
262   MSG_process_sleep(1000);
263
264   {
265     XBT_INFO("### Test: 75%% for Task1@%s, 25%% for Task2@%s", hostA_name, hostB_name);
266     launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed * 0.75);
267     launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed / 4);
268   }
269
270   MSG_process_sleep(1000);
271 }
272
273 static int master_main(int argc, char *argv[])
274 {
275   xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar();
276   msg_host_t pm0 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t);
277   msg_host_t pm1 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t);
278
279
280   {
281     XBT_INFO("# 1. Put a single task on a PM. ");
282     test_one_task(pm0);
283     XBT_INFO(" ");
284
285
286     XBT_INFO("# 2. Put two tasks on a PM.");
287     test_two_tasks(pm0, pm0);
288     XBT_INFO(" ");
289   }
290
291
292   {
293     msg_host_t vm0 = MSG_vm_create_core(pm0, "VM0");
294     MSG_vm_start(vm0);
295
296     XBT_INFO("# 3. Put a single task on a VM. ");
297     test_one_task(vm0);
298     XBT_INFO(" ");
299
300     XBT_INFO("# 4. Put two tasks on a VM.");
301     test_two_tasks(vm0, vm0);
302     XBT_INFO(" ");
303
304
305     MSG_vm_destroy(vm0);
306   }
307
308
309   {
310     msg_host_t vm0 = MSG_vm_create_core(pm0, "VM0");
311     MSG_vm_start(vm0);
312
313     XBT_INFO("# 6. Put a task on a PM and a task on a VM.");
314     test_two_tasks(pm0, vm0);
315     XBT_INFO(" ");
316
317
318     MSG_vm_destroy(vm0);
319   }
320
321
322   {
323     msg_host_t vm0 = MSG_vm_create_core(pm0, "VM0");
324     const double cpu_speed = MSG_get_host_speed(pm0);
325     MSG_vm_set_bound(vm0, cpu_speed / 10);
326     MSG_vm_start(vm0);
327
328     XBT_INFO("# 7. Put a single task on the VM capped by 10%%.");
329     test_one_task(vm0);
330     XBT_INFO(" ");
331
332     XBT_INFO("# 8. Put two tasks on the VM capped by 10%%.");
333     test_two_tasks(vm0, vm0);
334     XBT_INFO(" ");
335
336     XBT_INFO("# 9. Put a task on a PM and a task on the VM capped by 10%%.");
337     test_two_tasks(pm0, vm0);
338     XBT_INFO(" ");
339
340     MSG_vm_destroy(vm0);
341   }
342
343
344   {
345     msg_host_t vm0 = MSG_vm_create_core(pm0, "VM0");
346
347     s_ws_params_t params;
348     memset(&params, 0, sizeof(params));
349     params.ramsize = 1L * 1000 * 1000 * 1000; // 1Gbytes
350     MSG_host_set_params(vm0, &params);
351     MSG_vm_start(vm0);
352
353     const double cpu_speed = MSG_get_host_speed(pm0);
354     MSG_vm_start(vm0);
355
356     XBT_INFO("# 10. Test migration");
357     const double computation_amount = cpu_speed * 10;
358
359     XBT_INFO("# 10. (a) Put a task on a VM without any bound.");
360     launch_worker(vm0, "worker0", computation_amount, 0, 0);
361     MSG_process_sleep(1000);
362     XBT_INFO(" ");
363
364     XBT_INFO("# 10. (b) set 10%% bound to the VM, and then put a task on the VM.");
365     MSG_vm_set_bound(vm0, cpu_speed / 10);
366     launch_worker(vm0, "worker0", computation_amount, 0, 0);
367     MSG_process_sleep(1000);
368     XBT_INFO(" ");
369
370     XBT_INFO("# 10. (c) migrate");
371     MSG_vm_migrate(vm0, pm1);
372     XBT_INFO(" ");
373
374     XBT_INFO("# 10. (d) Put a task again on the VM.");
375     launch_worker(vm0, "worker0", computation_amount, 0, 0);
376     MSG_process_sleep(1000);
377     XBT_INFO(" ");
378
379     MSG_vm_destroy(vm0);
380   }
381
382
383   XBT_INFO("# 11. Change a bound dynamically.");
384   test_dynamic_change();
385
386   return 0;
387 }
388
389 static void launch_master(msg_host_t host)
390 {
391   const char *pr_name = "master_";
392   char **argv = xbt_new(char *, 2);
393   argv[0] = xbt_strdup(pr_name);
394   argv[1] = NULL;
395
396   MSG_process_create_with_arguments(pr_name, master_main, NULL, host, 1, argv);
397 }
398
399 int main(int argc, char *argv[])
400 {
401   /* Get the arguments */
402   MSG_init(&argc, argv);
403
404   /* load the platform file */
405   if (argc != 2) {
406     printf("Usage: %s example/msg/cloud/simple_plat.xml\n", argv[0]);
407     return 1;
408   }
409
410   MSG_create_environment(argv[1]);
411
412   xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar();
413   msg_host_t pm0 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t);
414   launch_master(pm0);
415
416   int res = MSG_main();
417   XBT_INFO("Bye (simulation time %g)", MSG_get_clock());
418
419
420   return !(res == MSG_OK);
421 }