Logo AND Algorithmique Numérique Distribuée

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