Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add a test program to see multicore behaviors.
[simgrid.git] / examples / msg / cloud / multicore.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"
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, "Messages specific for this msg example");
14
15
16 struct worker_data {
17         double computation_amount;
18 };
19
20
21 static int worker_main(int argc, char *argv[])
22 {
23   struct worker_data *params = MSG_process_get_data(MSG_process_self());
24   double computation_amount = params->computation_amount;
25
26   {
27     double clock_sta = MSG_get_clock();
28
29     msg_task_t task = MSG_task_create("Task", computation_amount, 0, NULL);
30     MSG_task_execute(task);
31     MSG_task_destroy(task);
32
33     double clock_end = MSG_get_clock();
34
35     double duration = clock_end - clock_sta;
36     double flops_per_sec = computation_amount / duration;
37
38     XBT_INFO("%s: amount %f duration %f (%f flops/s)",
39                     MSG_host_get_name(MSG_host_self()), computation_amount, duration, flops_per_sec);
40   }
41
42
43
44   xbt_free(params);
45
46   return 0;
47 }
48
49
50
51
52 static void test_one_task(msg_host_t hostA, double computation)
53 {
54
55   struct worker_data *params = xbt_new(struct worker_data, 1);
56   params->computation_amount = computation;
57
58   MSG_process_create("worker", worker_main, params, hostA);
59
60   //xbt_free(params);
61 }
62
63 #if 0
64 static void test_two_tasks(msg_host_t hostA, msg_host_t hostB)
65 {
66   const double cpu_speed = MSG_get_host_speed(hostA);
67   xbt_assert(cpu_speed == MSG_get_host_speed(hostB));
68   const double computation_amount = cpu_speed * 10;
69   const char *hostA_name = MSG_host_get_name(hostA);
70   const char *hostB_name = MSG_host_get_name(hostB);
71
72   {
73     XBT_INFO("### Test: no bound for Task1@%s, no bound for Task2@%s", hostA_name, hostB_name);
74     launch_worker(hostA, "worker0", computation_amount, 0, 0);
75     launch_worker(hostB, "worker1", computation_amount, 0, 0);
76   }
77
78   MSG_process_sleep(1000);
79
80   {
81     XBT_INFO("### Test: 0 for Task1@%s, 0 for Task2@%s (i.e., unlimited)", hostA_name, hostB_name);
82     launch_worker(hostA, "worker0", computation_amount, 1, 0);
83     launch_worker(hostB, "worker1", computation_amount, 1, 0);
84   }
85
86   MSG_process_sleep(1000);
87
88   {
89     XBT_INFO("### Test: 50%% for Task1@%s, 50%% for Task2@%s", hostA_name, hostB_name);
90     launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed / 2);
91     launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed / 2);
92   }
93
94   MSG_process_sleep(1000);
95
96   {
97     XBT_INFO("### Test: 25%% for Task1@%s, 25%% for Task2@%s", hostA_name, hostB_name);
98     launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed / 4);
99     launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed / 4);
100   }
101
102   MSG_process_sleep(1000);
103
104   {
105     XBT_INFO("### Test: 75%% for Task1@%s, 100%% for Task2@%s", hostA_name, hostB_name);
106     launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed * 0.75);
107     launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed);
108   }
109
110   MSG_process_sleep(1000);
111
112   {
113     XBT_INFO("### Test: no bound for Task1@%s, 25%% for Task2@%s", hostA_name, hostB_name);
114     launch_worker(hostA, "worker0", computation_amount, 0, 0);
115     launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed / 4);
116   }
117
118   MSG_process_sleep(1000);
119
120   {
121     XBT_INFO("### Test: 75%% for Task1@%s, 25%% for Task2@%s", hostA_name, hostB_name);
122     launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed * 0.75);
123     launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed / 4);
124   }
125
126   MSG_process_sleep(1000);
127 }
128 #endif
129
130 static void test_pm(void)
131 {
132   xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar();
133   msg_host_t pm0 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t);
134   msg_host_t pm1 = xbt_dynar_get_as(hosts_dynar, 1, msg_host_t);
135   msg_host_t pm2 = xbt_dynar_get_as(hosts_dynar, 2, msg_host_t);
136
137   const double cpu_speed = MSG_get_host_speed(pm0);
138   const double computation_amount = cpu_speed * 10;
139
140   {
141     XBT_INFO("# 1. Put a single task on each PM. ");
142     test_one_task(pm0, computation_amount);
143     MSG_process_sleep(100);
144     test_one_task(pm1, computation_amount);
145     MSG_process_sleep(100);
146     test_one_task(pm2, computation_amount);
147   }
148
149   MSG_process_sleep(100);
150
151   {
152     XBT_INFO("# 2. Put 2 tasks on each PM. ");
153     test_one_task(pm0, computation_amount);
154     test_one_task(pm0, computation_amount);
155     MSG_process_sleep(100);
156
157     test_one_task(pm1, computation_amount);
158     test_one_task(pm1, computation_amount);
159     MSG_process_sleep(100);
160
161     test_one_task(pm2, computation_amount);
162     test_one_task(pm2, computation_amount);
163   }
164
165   MSG_process_sleep(100);
166
167   {
168     XBT_INFO("# 3. Put 4 tasks on each PM. ");
169     test_one_task(pm0, computation_amount);
170     test_one_task(pm0, computation_amount);
171     test_one_task(pm0, computation_amount);
172     test_one_task(pm0, computation_amount);
173     MSG_process_sleep(100);
174
175     test_one_task(pm1, computation_amount);
176     test_one_task(pm1, computation_amount);
177     test_one_task(pm1, computation_amount);
178     test_one_task(pm1, computation_amount);
179     MSG_process_sleep(100);
180
181     test_one_task(pm2, computation_amount);
182     test_one_task(pm2, computation_amount);
183     test_one_task(pm2, computation_amount);
184     test_one_task(pm2, computation_amount);
185   }
186
187   MSG_process_sleep(100);
188 }
189
190
191 static void test_vm(void)
192 {
193   xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar();
194   msg_host_t pm0 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t);
195   msg_host_t pm1 = xbt_dynar_get_as(hosts_dynar, 1, msg_host_t);
196   msg_host_t pm2 = xbt_dynar_get_as(hosts_dynar, 2, msg_host_t);
197
198
199   const double cpu_speed = MSG_get_host_speed(pm0);
200   const double computation_amount = cpu_speed * 10;
201
202
203   {
204     msg_host_t vm0 = MSG_vm_create_core(pm0, "vm0");
205     msg_host_t vm1 = MSG_vm_create_core(pm1, "vm1");
206     msg_host_t vm2 = MSG_vm_create_core(pm2, "vm2");
207
208     XBT_INFO("# 1. Put a single task on each VM.");
209     test_one_task(vm0, computation_amount);
210     MSG_process_sleep(100);
211
212     test_one_task(vm1, computation_amount);
213     MSG_process_sleep(100);
214
215     test_one_task(vm2, computation_amount);
216     MSG_process_sleep(100);
217
218     MSG_vm_destroy(vm0);
219     MSG_vm_destroy(vm1);
220     MSG_vm_destroy(vm2);
221   }
222
223
224   {
225     msg_host_t vm0 = MSG_vm_create_core(pm0, "vm0");
226     msg_host_t vm1 = MSG_vm_create_core(pm1, "vm1");
227     msg_host_t vm2 = MSG_vm_create_core(pm2, "vm2");
228
229     XBT_INFO("# 2. Put 2 tasks on each VM.");
230     test_one_task(vm0, computation_amount);
231     test_one_task(vm0, computation_amount);
232     MSG_process_sleep(100);
233
234     test_one_task(vm1, computation_amount);
235     test_one_task(vm1, computation_amount);
236     MSG_process_sleep(100);
237
238     test_one_task(vm2, computation_amount);
239     test_one_task(vm2, computation_amount);
240     MSG_process_sleep(100);
241
242     MSG_vm_destroy(vm0);
243     MSG_vm_destroy(vm1);
244     MSG_vm_destroy(vm2);
245   }
246
247
248   {
249     msg_host_t vm0 = MSG_vm_create_core(pm0, "vm0");
250     msg_host_t vm1 = MSG_vm_create_core(pm1, "vm1");
251     msg_host_t vm2 = MSG_vm_create_core(pm2, "vm2");
252
253     XBT_INFO("# 3. Put a task on each VM, and put a task on its PM.");
254     test_one_task(vm0, computation_amount);
255     test_one_task(pm0, computation_amount);
256     MSG_process_sleep(100);
257
258     test_one_task(vm1, computation_amount);
259     test_one_task(pm1, computation_amount);
260     MSG_process_sleep(100);
261
262     test_one_task(vm2, computation_amount);
263     test_one_task(pm2, computation_amount);
264     MSG_process_sleep(100);
265
266     MSG_vm_destroy(vm0);
267     MSG_vm_destroy(vm1);
268     MSG_vm_destroy(vm2);
269   }
270
271
272   {
273     {
274        /* 1-core PM */
275        XBT_INFO("# 4. Put 2 VMs on a 1-core PM.");
276        msg_host_t vm0 = MSG_vm_create_core(pm0, "vm0");
277        msg_host_t vm1 = MSG_vm_create_core(pm0, "vm1");
278       
279        test_one_task(vm0, computation_amount);
280        test_one_task(vm1, computation_amount);
281        MSG_process_sleep(100);
282       
283        MSG_vm_destroy(vm0);
284        MSG_vm_destroy(vm1);
285     }
286
287     {
288        /* 2-core PM */
289        XBT_INFO("# 5. Put 2 VMs on a 2-core PM.");
290        msg_host_t vm0 = MSG_vm_create_core(pm1, "vm0");
291        msg_host_t vm1 = MSG_vm_create_core(pm1, "vm1");
292
293        test_one_task(vm0, computation_amount);
294        test_one_task(vm1, computation_amount);
295        MSG_process_sleep(100);
296
297        MSG_vm_destroy(vm0);
298        MSG_vm_destroy(vm1);
299     }
300
301     {
302        /* 2-core PM */
303        XBT_INFO("# 6. Put 2 VMs on a 2-core PM and 1 task on the PM.");
304        msg_host_t vm0 = MSG_vm_create_core(pm1, "vm0");
305        msg_host_t vm1 = MSG_vm_create_core(pm1, "vm1");
306
307        test_one_task(vm0, computation_amount);
308        test_one_task(vm1, computation_amount);
309        test_one_task(pm1, computation_amount);
310        MSG_process_sleep(100);
311
312        MSG_vm_destroy(vm0);
313        MSG_vm_destroy(vm1);
314     }
315
316     {
317        /* 2-core PM */
318        XBT_INFO("# 7. Put 2 VMs and 2 tasks on a 2-core PM. Put two tasks on one of the VMs.");
319        msg_host_t vm0 = MSG_vm_create_core(pm1, "vm0");
320        msg_host_t vm1 = MSG_vm_create_core(pm1, "vm1");
321        test_one_task(pm1, computation_amount);
322        test_one_task(pm1, computation_amount);
323
324        /* Reduce computation_amount to make all tasks finish at the same time. Simplify results. */
325        test_one_task(vm0, computation_amount / 2);
326        test_one_task(vm0, computation_amount / 2);
327        test_one_task(vm1, computation_amount);
328        MSG_process_sleep(100);
329
330        MSG_vm_destroy(vm0);
331        MSG_vm_destroy(vm1);
332     }
333
334     {
335        /* 2-core PM */
336        XBT_INFO("# 8. Put 2 VMs and a task on a 2-core PM. Cap the load of VM1 at 50%%.");
337        /* This is a tricky case. The process schedular of the host OS may not work as expected. */
338         
339        /* VM0 gets 50%. VM1 and VM2 get 75%, respectively. */
340        msg_host_t vm0 = MSG_vm_create_core(pm1, "vm0");
341        MSG_vm_set_bound(vm0, cpu_speed / 2);
342        msg_host_t vm1 = MSG_vm_create_core(pm1, "vm1");
343        test_one_task(pm1, computation_amount);
344
345        test_one_task(vm0, computation_amount);
346        test_one_task(vm1, computation_amount);
347
348        MSG_process_sleep(100);
349
350        MSG_vm_destroy(vm0);
351        MSG_vm_destroy(vm1);
352     }
353
354
355     /* In all the above cases, tasks finish at the same time.
356      * TODO: more complex cases must be done.
357      **/
358
359 #if 0
360     {
361        /* 2-core PM */
362        XBT_INFO("# 8. Put 2 VMs and a task on a 2-core PM. Put two tasks on one of the VMs.");
363        msg_host_t vm0 = MSG_vm_create_core(pm1, "vm0");
364        msg_host_t vm1 = MSG_vm_create_core(pm1, "vm1");
365
366        test_one_task(vm0, computation_amount);
367        test_one_task(vm0, computation_amount);
368        test_one_task(vm1, computation_amount);
369        test_one_task(pm1, computation_amount);
370        MSG_process_sleep(100);
371
372        MSG_vm_destroy(vm0);
373        MSG_vm_destroy(vm1);
374     }
375 #endif
376   }
377 }
378
379
380
381 static int master_main(int argc, char *argv[])
382 {
383   XBT_INFO("=== Test PM ===");
384   test_pm();
385
386   XBT_INFO(" ");
387   XBT_INFO(" ");
388   XBT_INFO("=== Test VM ===");
389   test_vm();
390
391   return 0;
392 }
393
394
395
396
397
398 int main(int argc, char *argv[])
399 {
400   /* Get the arguments */
401   MSG_init(&argc, argv);
402
403   /* load the platform file */
404   if (argc != 2) {
405     printf("Usage: %s examples/msg/cloud/multicore_plat.xml\n", argv[0]);
406     return 1;
407   }
408
409   MSG_create_environment(argv[1]);
410
411   xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar();
412   msg_host_t pm0 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t);
413   msg_host_t pm1 = xbt_dynar_get_as(hosts_dynar, 1, msg_host_t);
414   msg_host_t pm2 = xbt_dynar_get_as(hosts_dynar, 2, msg_host_t);
415
416
417   XBT_INFO("%s: %d core(s), %f flops/s per each", MSG_host_get_name(pm0), MSG_get_host_core(pm0), MSG_get_host_speed(pm0));
418   XBT_INFO("%s: %d core(s), %f flops/s per each", MSG_host_get_name(pm1), MSG_get_host_core(pm1), MSG_get_host_speed(pm1));
419   XBT_INFO("%s: %d core(s), %f flops/s per each", MSG_host_get_name(pm2), MSG_get_host_core(pm2), MSG_get_host_speed(pm2));
420
421
422
423   MSG_process_create("master", master_main, NULL, pm0);
424
425
426
427
428   int res = MSG_main();
429   XBT_INFO("Bye (simulation time %g)", MSG_get_clock());
430
431
432   return !(res == MSG_OK);
433 }