Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge pull request #2 from mquinson/master
[simgrid.git] / examples / msg / cloud / bound.c
1 /* Copyright (c) 2007-2015. 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 "simgrid/msg.h"        /* Yeah! If you want to use msg, you need to include simgrid/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 = xbt_str_parse_double(argv[1], "Invalid computation amount: %s");
28   int use_bound = xbt_str_parse_int(argv[2], "Second parameter (use_bound) should be 0 or 1 but is: %s");
29   double bound = xbt_str_parse_double(argv[3], "Invalid bound: %s");
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_flops_amount(task0);
96   double task1_remain_prev = MSG_task_get_flops_amount(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_flops_amount(task0);
108       double task1_remain_now = MSG_task_get_flops_amount(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   {
139     XBT_INFO("### Test: no bound for Task1@%s", hostA_name);
140     launch_worker(hostA, "worker0", computation_amount, 0, 0);
141   }
142
143   MSG_process_sleep(1000);
144
145   {
146     XBT_INFO("### Test: 50%% for Task1@%s", hostA_name);
147     launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed / 2);
148   }
149
150   MSG_process_sleep(1000);
151
152   {
153     XBT_INFO("### Test: 33%% for Task1@%s", hostA_name);
154     launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed / 3);
155   }
156
157   MSG_process_sleep(1000);
158
159   {
160     XBT_INFO("### Test: zero for Task1@%s (i.e., unlimited)", hostA_name);
161     launch_worker(hostA, "worker0", computation_amount, 1, 0);
162   }
163
164   MSG_process_sleep(1000);
165
166   {
167     XBT_INFO("### Test: 200%% for Task1@%s (i.e., meaningless)", hostA_name);
168     launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed * 2);
169   }
170
171   MSG_process_sleep(1000);
172 }
173
174
175 static void test_two_tasks(msg_host_t hostA, msg_host_t hostB)
176 {
177   const double cpu_speed = MSG_get_host_speed(hostA);
178   xbt_assert(cpu_speed == MSG_get_host_speed(hostB));
179   const double computation_amount = cpu_speed * 10;
180   const char *hostA_name = MSG_host_get_name(hostA);
181   const char *hostB_name = MSG_host_get_name(hostB);
182
183   {
184     XBT_INFO("### Test: no bound for Task1@%s, no bound for Task2@%s", hostA_name, hostB_name);
185     launch_worker(hostA, "worker0", computation_amount, 0, 0);
186     launch_worker(hostB, "worker1", computation_amount, 0, 0);
187   }
188
189   MSG_process_sleep(1000);
190
191   {
192     XBT_INFO("### Test: 0 for Task1@%s, 0 for Task2@%s (i.e., unlimited)", hostA_name, hostB_name);
193     launch_worker(hostA, "worker0", computation_amount, 1, 0);
194     launch_worker(hostB, "worker1", computation_amount, 1, 0);
195   }
196
197   MSG_process_sleep(1000);
198
199   {
200     XBT_INFO("### Test: 50%% for Task1@%s, 50%% for Task2@%s", hostA_name, hostB_name);
201     launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed / 2);
202     launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed / 2);
203   }
204
205   MSG_process_sleep(1000);
206
207   {
208     XBT_INFO("### Test: 25%% for Task1@%s, 25%% for Task2@%s", hostA_name, hostB_name);
209     launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed / 4);
210     launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed / 4);
211   }
212
213   MSG_process_sleep(1000);
214
215   {
216     XBT_INFO("### Test: 75%% for Task1@%s, 100%% for Task2@%s", hostA_name, hostB_name);
217     launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed * 0.75);
218     launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed);
219   }
220
221   MSG_process_sleep(1000);
222
223   {
224     XBT_INFO("### Test: no bound for Task1@%s, 25%% for Task2@%s", hostA_name, hostB_name);
225     launch_worker(hostA, "worker0", computation_amount, 0, 0);
226     launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed / 4);
227   }
228
229   MSG_process_sleep(1000);
230
231   {
232     XBT_INFO("### Test: 75%% for Task1@%s, 25%% for Task2@%s", hostA_name, hostB_name);
233     launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed * 0.75);
234     launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed / 4);
235   }
236
237   MSG_process_sleep(1000);
238 }
239
240 static int master_main(int argc, char *argv[])
241 {
242   xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar();
243   msg_host_t pm0 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t);
244   msg_host_t pm1 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t);
245
246
247   {
248     XBT_INFO("# 1. Put a single task on a PM. ");
249     test_one_task(pm0);
250     XBT_INFO(" ");
251
252
253     XBT_INFO("# 2. Put two tasks on a PM.");
254     test_two_tasks(pm0, pm0);
255     XBT_INFO(" ");
256   }
257
258
259   {
260     msg_host_t vm0 = MSG_vm_create_core(pm0, "VM0");
261     MSG_vm_start(vm0);
262
263     XBT_INFO("# 3. Put a single task on a VM. ");
264     test_one_task(vm0);
265     XBT_INFO(" ");
266
267     XBT_INFO("# 4. Put two tasks on a VM.");
268     test_two_tasks(vm0, vm0);
269     XBT_INFO(" ");
270
271
272     MSG_vm_destroy(vm0);
273   }
274
275
276   {
277     msg_host_t vm0 = MSG_vm_create_core(pm0, "VM0");
278     MSG_vm_start(vm0);
279
280     XBT_INFO("# 6. Put a task on a PM and a task on a VM.");
281     test_two_tasks(pm0, vm0);
282     XBT_INFO(" ");
283
284
285     MSG_vm_destroy(vm0);
286   }
287
288
289   {
290     msg_host_t vm0 = MSG_vm_create_core(pm0, "VM0");
291     const double cpu_speed = MSG_get_host_speed(pm0);
292     MSG_vm_set_bound(vm0, cpu_speed / 10);
293     MSG_vm_start(vm0);
294
295     XBT_INFO("# 7. Put a single task on the VM capped by 10%%.");
296     test_one_task(vm0);
297     XBT_INFO(" ");
298
299     XBT_INFO("# 8. Put two tasks on the VM capped by 10%%.");
300     test_two_tasks(vm0, vm0);
301     XBT_INFO(" ");
302
303     XBT_INFO("# 9. Put a task on a PM and a task on the VM capped by 10%%.");
304     test_two_tasks(pm0, vm0);
305     XBT_INFO(" ");
306
307     MSG_vm_destroy(vm0);
308   }
309
310
311   {
312     msg_host_t vm0 = MSG_vm_create_core(pm0, "VM0");
313
314     s_vm_params_t params;
315     memset(&params, 0, sizeof(params));
316     params.ramsize = 1L * 1000 * 1000 * 1000; // 1Gbytes
317     MSG_host_set_params(vm0, &params);
318     MSG_vm_start(vm0);
319
320     const double cpu_speed = MSG_get_host_speed(pm0);
321     MSG_vm_start(vm0);
322
323     XBT_INFO("# 10. Test migration");
324     const double computation_amount = cpu_speed * 10;
325
326     XBT_INFO("# 10. (a) Put a task on a VM without any bound.");
327     launch_worker(vm0, "worker0", computation_amount, 0, 0);
328     MSG_process_sleep(1000);
329     XBT_INFO(" ");
330
331     XBT_INFO("# 10. (b) set 10%% bound to the VM, and then put a task on the VM.");
332     MSG_vm_set_bound(vm0, cpu_speed / 10);
333     launch_worker(vm0, "worker0", computation_amount, 0, 0);
334     MSG_process_sleep(1000);
335     XBT_INFO(" ");
336
337     XBT_INFO("# 10. (c) migrate");
338     MSG_vm_migrate(vm0, pm1);
339     XBT_INFO(" ");
340
341     XBT_INFO("# 10. (d) Put a task again on the VM.");
342     launch_worker(vm0, "worker0", computation_amount, 0, 0);
343     MSG_process_sleep(1000);
344     XBT_INFO(" ");
345
346     MSG_vm_destroy(vm0);
347   }
348
349
350   XBT_INFO("# 11. Change a bound dynamically.");
351   test_dynamic_change();
352
353   return 0;
354 }
355
356 static void launch_master(msg_host_t host)
357 {
358   const char *pr_name = "master_";
359   char **argv = xbt_new(char *, 2);
360   argv[0] = xbt_strdup(pr_name);
361   argv[1] = NULL;
362
363   MSG_process_create_with_arguments(pr_name, master_main, NULL, host, 1, argv);
364 }
365
366 int main(int argc, char *argv[])
367 {
368   /* Get the arguments */
369   MSG_init(&argc, argv);
370
371   /* load the platform file */
372   if (argc != 2) {
373     printf("Usage: %s example/msg/cloud/simple_plat.xml\n", argv[0]);
374     return 1;
375   }
376
377   MSG_create_environment(argv[1]);
378
379   xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar();
380   msg_host_t pm0 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t);
381   launch_master(pm0);
382
383   int res = MSG_main();
384   XBT_INFO("Bye (simulation time %g)", MSG_get_clock());
385
386
387   return !(res == MSG_OK);
388 }