Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Use values of type double.
[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 /* FIXME: */
76 #define DOUBLE_MAX 1e11
77
78 static void test_dynamic_change(void)
79 {
80   xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar();
81   msg_host_t pm0 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t);
82
83   msg_host_t vm0 = MSG_vm_create_core(pm0, "VM0");
84   msg_host_t vm1 = MSG_vm_create_core(pm0, "VM1");
85   MSG_vm_start(vm0);
86   MSG_vm_start(vm1);
87
88   msg_task_t task0 = MSG_task_create("Task0", DOUBLE_MAX, 0, NULL);
89   msg_task_t task1 = MSG_task_create("Task1", DOUBLE_MAX, 0, NULL);
90   msg_process_t pr0 = MSG_process_create("worker0", worker_busy_loop_main, &task0, vm0);
91   msg_process_t pr1 = MSG_process_create("worker1", worker_busy_loop_main, &task1, vm1);
92
93
94   double task0_remain_prev = MSG_task_get_remaining_computation(task0);
95   double task1_remain_prev = MSG_task_get_remaining_computation(task1);
96
97   {
98     const double cpu_speed = MSG_get_host_speed(pm0);
99     int i = 0;
100     for (i = 0; i < 10; i++) {
101       double new_bound = (cpu_speed / 10) * i;
102       XBT_INFO("set bound of VM1 to %f", new_bound);
103       MSG_vm_set_bound(vm1, new_bound);
104       MSG_process_sleep(100);
105
106       double task0_remain_now = MSG_task_get_remaining_computation(task0);
107       double task1_remain_now = MSG_task_get_remaining_computation(task1);
108
109       double task0_flops_per_sec = task0_remain_prev - task0_remain_now;
110       double task1_flops_per_sec = task1_remain_prev - task1_remain_now;
111
112       XBT_INFO("Task0@VM0: %f flops/s", task0_flops_per_sec / 100);
113       XBT_INFO("Task1@VM1: %f flops/s", task1_flops_per_sec / 100);
114
115       task0_remain_prev = task0_remain_now;
116       task1_remain_prev = task1_remain_now;
117     }
118   }
119
120   MSG_process_kill(pr0);
121   MSG_process_kill(pr1);
122   
123   MSG_vm_destroy(vm0);
124   MSG_vm_destroy(vm1);
125 }
126
127
128
129 static void test_one_task(msg_host_t hostA)
130 {
131   const double cpu_speed = MSG_get_host_speed(hostA);
132   const double computation_amount = cpu_speed * 10;
133   const char *hostA_name = MSG_host_get_name(hostA);
134
135   XBT_INFO("### Test: with/without MSG_task_set_bound");
136
137 #if 0
138   /* Easy-to-understand code (without calling MSG_task_set_bound) */
139   {
140     double clock_sta = MSG_get_clock();
141
142     msg_task_t task = MSG_task_create("Task", computation_amount, 0, NULL);
143     MSG_task_execute(task);
144     MSG_task_destroy(task);
145
146     double clock_end = MSG_get_clock();
147     double duration = clock_end - clock_sta;
148     double flops_per_sec = computation_amount / duration;
149
150     XBT_INFO("not bound => duration %f (%f flops/s)", duration, flops_per_sec);
151   }
152
153   /* Easy-to-understand code (with calling MSG_task_set_bound) */
154   {
155     double clock_sta = MSG_get_clock();
156
157     msg_task_t task = MSG_task_create("Task", computation_amount, 0, NULL);
158     MSG_task_set_bound(task, cpu_speed / 2);
159     MSG_task_execute(task);
160     MSG_task_destroy(task);
161
162     double clock_end = MSG_get_clock();
163     double duration = clock_end - clock_sta;
164     double flops_per_sec = computation_amount / duration;
165
166     XBT_INFO("bound to 0.5 => duration %f (%f flops/s)", duration, flops_per_sec);
167   }
168 #endif
169
170   {
171     XBT_INFO("### Test: no bound for Task1@%s", hostA_name);
172     launch_worker(hostA, "worker0", computation_amount, 0, 0);
173   }
174
175   MSG_process_sleep(1000);
176
177   {
178     XBT_INFO("### Test: 50%% for Task1@%s", hostA_name);
179     launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed / 2);
180   }
181
182   MSG_process_sleep(1000);
183
184   {
185     XBT_INFO("### Test: 33%% for Task1@%s", hostA_name);
186     launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed / 3);
187   }
188
189   MSG_process_sleep(1000);
190
191   {
192     XBT_INFO("### Test: zero for Task1@%s (i.e., unlimited)", hostA_name);
193     launch_worker(hostA, "worker0", computation_amount, 1, 0);
194   }
195
196   MSG_process_sleep(1000);
197
198   {
199     XBT_INFO("### Test: 200%% for Task1@%s (i.e., meaningless)", hostA_name);
200     launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed * 2);
201   }
202
203   MSG_process_sleep(1000);
204 }
205
206
207 static void test_two_tasks(msg_host_t hostA, msg_host_t hostB)
208 {
209   const double cpu_speed = MSG_get_host_speed(hostA);
210   xbt_assert(cpu_speed == MSG_get_host_speed(hostB));
211   const double computation_amount = cpu_speed * 10;
212   const char *hostA_name = MSG_host_get_name(hostA);
213   const char *hostB_name = MSG_host_get_name(hostB);
214
215   {
216     XBT_INFO("### Test: no bound for Task1@%s, no bound for Task2@%s", hostA_name, hostB_name);
217     launch_worker(hostA, "worker0", computation_amount, 0, 0);
218     launch_worker(hostB, "worker1", computation_amount, 0, 0);
219   }
220
221   MSG_process_sleep(1000);
222
223   {
224     XBT_INFO("### Test: 0 for Task1@%s, 0 for Task2@%s (i.e., unlimited)", hostA_name, hostB_name);
225     launch_worker(hostA, "worker0", computation_amount, 1, 0);
226     launch_worker(hostB, "worker1", computation_amount, 1, 0);
227   }
228
229   MSG_process_sleep(1000);
230
231   {
232     XBT_INFO("### Test: 50%% for Task1@%s, 50%% for Task2@%s", hostA_name, hostB_name);
233     launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed / 2);
234     launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed / 2);
235   }
236
237   MSG_process_sleep(1000);
238
239   {
240     XBT_INFO("### Test: 25%% for Task1@%s, 25%% for Task2@%s", hostA_name, hostB_name);
241     launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed / 4);
242     launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed / 4);
243   }
244
245   MSG_process_sleep(1000);
246
247   {
248     XBT_INFO("### Test: 75%% for Task1@%s, 100%% for Task2@%s", hostA_name, hostB_name);
249     launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed * 0.75);
250     launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed);
251   }
252
253   MSG_process_sleep(1000);
254
255   {
256     XBT_INFO("### Test: no bound for Task1@%s, 25%% for Task2@%s", hostA_name, hostB_name);
257     launch_worker(hostA, "worker0", computation_amount, 0, 0);
258     launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed / 4);
259   }
260
261   MSG_process_sleep(1000);
262
263   {
264     XBT_INFO("### Test: 75%% for Task1@%s, 25%% for Task2@%s", hostA_name, hostB_name);
265     launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed * 0.75);
266     launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed / 4);
267   }
268
269   MSG_process_sleep(1000);
270 }
271
272 static int master_main(int argc, char *argv[])
273 {
274   xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar();
275   msg_host_t pm0 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t);
276
277
278   {
279     XBT_INFO("# 1. Put a single task on a PM. ");
280     test_one_task(pm0);
281     XBT_INFO(" ");
282
283
284     XBT_INFO("# 2. Put two tasks on a PM.");
285     test_two_tasks(pm0, pm0);
286     XBT_INFO(" ");
287   }
288
289
290   {
291     msg_host_t vm0 = MSG_vm_create_core(pm0, "VM0");
292     MSG_vm_start(vm0);
293
294     XBT_INFO("# 3. Put a single task on a VM. ");
295     test_one_task(vm0);
296     XBT_INFO(" ");
297
298     XBT_INFO("# 4. Put two tasks on a VM.");
299     test_two_tasks(vm0, vm0);
300     XBT_INFO(" ");
301
302
303     MSG_vm_destroy(vm0);
304   }
305
306
307   {
308     msg_host_t vm0 = MSG_vm_create_core(pm0, "VM0");
309     MSG_vm_start(vm0);
310
311     XBT_INFO("# 6. Put a task on a PM and a task on a VM.");
312     test_two_tasks(pm0, vm0);
313     XBT_INFO(" ");
314
315
316     MSG_vm_destroy(vm0);
317   }
318
319
320   {
321     msg_host_t vm0 = MSG_vm_create_core(pm0, "VM0");
322     const double cpu_speed = MSG_get_host_speed(pm0);
323     MSG_vm_set_bound(vm0, cpu_speed / 10);
324     MSG_vm_start(vm0);
325
326     XBT_INFO("# 7. Put a single task on the VM capped by 10%%.");
327     test_one_task(vm0);
328     XBT_INFO(" ");
329
330     XBT_INFO("# 8. Put two tasks on the VM capped by 10%%.");
331     test_two_tasks(vm0, vm0);
332     XBT_INFO(" ");
333
334     XBT_INFO("# 9. Put a task on a PM and a task on the VM capped by 10%%.");
335     test_two_tasks(pm0, vm0);
336     XBT_INFO(" ");
337
338     MSG_vm_destroy(vm0);
339   }
340
341
342   XBT_INFO("# 10. Change a bound dynamically.");
343   test_dynamic_change();
344
345   return 0;
346 }
347
348 static void launch_master(msg_host_t host)
349 {
350   const char *pr_name = "master_";
351   char **argv = xbt_new(char *, 2);
352   argv[0] = xbt_strdup(pr_name);
353   argv[1] = NULL;
354
355   MSG_process_create_with_arguments(pr_name, master_main, NULL, host, 1, argv);
356 }
357
358 int main(int argc, char *argv[])
359 {
360   /* Get the arguments */
361   MSG_init(&argc, argv);
362
363   /* load the platform file */
364   if (argc != 2) {
365     printf("Usage: %s example/msg/cloud/simple_plat.xml\n", argv[0]);
366     return 1;
367   }
368
369   MSG_create_environment(argv[1]);
370
371   xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar();
372   msg_host_t pm0 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t);
373   launch_master(pm0);
374
375   int res = MSG_main();
376   XBT_INFO("Bye (simulation time %g)", MSG_get_clock());
377
378
379   return !(res == MSG_OK);
380 }