Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
change the way computation tracing is handled in smpi
[simgrid.git] / testsuite / xbt / parmap_bench.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <xbt/dynar.h>
4 #include <xbt/parmap.h>
5 #include <xbt/sysdep.h>
6 #include <internal_config.h>        /* HAVE_FUTEX_H */
7 #include "simgrid/simix.h"
8 #include "xbt/xbt_os_time.h"
9
10 #define MODES_DEFAULT 0x7
11 #define TIMEOUT 10.0
12 #define ARRAY_SIZE 10007
13 #define FIBO_MAX 25
14
15 void (*fun_to_apply)(void *);
16
17 static const char *parmap_mode_name(e_xbt_parmap_mode_t mode)
18 {
19   static char name[80];
20   switch (mode) {
21   case XBT_PARMAP_POSIX:
22     snprintf(name, sizeof name, "POSIX");
23     break;
24   case XBT_PARMAP_FUTEX:
25     snprintf(name, sizeof name, "FUTEX");
26     break;
27   case XBT_PARMAP_BUSY_WAIT:
28     snprintf(name, sizeof name, "BUSY_WAIT");
29     break;
30   case XBT_PARMAP_DEFAULT:
31     snprintf(name, sizeof name, "DEFAULT");
32     break;
33   default:
34     snprintf(name, sizeof name, "UNKNOWN(%d)", (int)mode);
35     break;
36   }
37   return name;
38 }
39
40 static int parmap_skip_mode(e_xbt_parmap_mode_t mode)
41 {
42   switch (mode) {
43 #ifndef HAVE_FUTEX_H
44   case XBT_PARMAP_FUTEX:
45     printf("not available\n");
46     return 1;
47 #endif
48   default:
49     return 0;
50   }
51 }
52
53 static unsigned fibonacci(unsigned n)
54 {
55   if (n < 2)
56     return n;
57   else
58     return fibonacci(n - 1) + fibonacci(n - 2);
59 }
60
61 static void fun_small_comp(void *arg)
62 {
63   unsigned *u = arg;
64   *u = 2 * *u + 1;
65 }
66
67 static void fun_big_comp(void *arg)
68 {
69   unsigned *u = arg;
70   *u = fibonacci(*u % FIBO_MAX);
71 }
72
73 static void array_new(unsigned **a, xbt_dynar_t *data)
74 {
75   int i;
76   *a = xbt_malloc(ARRAY_SIZE * sizeof **a);
77   *data = xbt_dynar_new(sizeof *a, NULL);
78   xbt_dynar_shrink(*data, ARRAY_SIZE);
79   for (i = 0 ; i < ARRAY_SIZE ; i++) {
80     (*a)[i] = i;
81     xbt_dynar_push_as(*data, void*, &(*a)[i]);
82   }
83 }
84
85 static void bench_parmap_full(int nthreads, e_xbt_parmap_mode_t mode)
86 {
87   unsigned *a;
88   xbt_dynar_t data;
89   xbt_parmap_t parmap;
90   int i;
91   double start_time, elapsed_time;
92
93   printf("** mode = %-15s ", parmap_mode_name(mode));
94   fflush(stdout);
95
96   if (parmap_skip_mode(mode))
97     return;
98
99   array_new(&a, &data);
100
101   i = 0;
102   start_time = xbt_os_time();
103   do {
104     parmap = xbt_parmap_new(nthreads, mode);
105     xbt_parmap_apply(parmap, fun_to_apply, data);
106     xbt_parmap_destroy(parmap);
107     elapsed_time = xbt_os_time() - start_time;
108     i++;
109   } while (elapsed_time < TIMEOUT);
110
111   printf("ran %d times in %g seconds (%g/s)\n",
112          i, elapsed_time, i / elapsed_time);
113
114   xbt_dynar_free(&data);
115   xbt_free(a);
116 }
117
118 static void bench_parmap_apply(int nthreads, e_xbt_parmap_mode_t mode)
119 {
120   unsigned *a;
121   xbt_dynar_t data;
122   xbt_parmap_t parmap;
123   int i;
124   double start_time, elapsed_time;
125
126   printf("** mode = %-15s ", parmap_mode_name(mode));
127   fflush(stdout);
128
129   if (parmap_skip_mode(mode))
130     return;
131
132   array_new(&a, &data);
133
134   parmap = xbt_parmap_new(nthreads, mode);
135   i = 0;
136   start_time = xbt_os_time();
137   do {
138     xbt_parmap_apply(parmap, fun_to_apply, data);
139     elapsed_time = xbt_os_time() - start_time;
140     i++;
141   } while (elapsed_time < TIMEOUT);
142   xbt_parmap_destroy(parmap);
143
144   printf("ran %d times in %g seconds (%g/s)\n",
145          i, elapsed_time, i / elapsed_time);
146
147   xbt_dynar_free(&data);
148   xbt_free(a);
149 }
150
151 static void bench_all_modes(void (*bench_fun)(int, e_xbt_parmap_mode_t),
152                             int nthreads, unsigned modes)
153 {
154   e_xbt_parmap_mode_t all_modes[] = {
155     XBT_PARMAP_POSIX, XBT_PARMAP_FUTEX,
156     XBT_PARMAP_BUSY_WAIT, XBT_PARMAP_DEFAULT
157   };
158   unsigned i;
159   for (i = 0 ; i < sizeof all_modes / sizeof all_modes[0] ; i++) {
160     if (1U << i & modes)
161       bench_fun(nthreads, all_modes[i]);
162   }
163 }
164
165 int main(int argc, char *argv[])
166 {
167   int nthreads;
168   unsigned modes = MODES_DEFAULT;
169
170   SIMIX_global_init(&argc, argv);
171
172   if (argc != 2 && argc != 3) {
173     fprintf(stderr,
174             "Usage: %s nthreads [modes]\n"
175             "    nthreads - number of working threads\n"
176             "    modes    - bitmask of modes to test\n",
177             argv[0]);
178     return EXIT_FAILURE;
179   }
180   nthreads = atoi(argv[1]);
181   if (nthreads < 1) {
182     fprintf(stderr, "ERROR: invalid thread count: %d\n", nthreads);
183     return EXIT_FAILURE;
184   }
185   if (argc == 3)
186     modes = strtol(argv[2], NULL, 0);
187
188   printf("Parmap benchmark with %d workers (modes = %#x)...\n\n",
189          nthreads, modes);
190
191   fun_to_apply = fun_small_comp;
192
193   printf("Benchmark for parmap create+apply+destroy (small comp):\n");
194   bench_all_modes(bench_parmap_full, nthreads, modes);
195   printf("\n");
196
197   printf("Benchmark for parmap apply only (small comp):\n");
198   bench_all_modes(bench_parmap_apply, nthreads, modes);
199   printf("\n");
200
201   fun_to_apply = fun_big_comp;
202
203   printf("Benchmark for parmap create+apply+destroy (big comp):\n");
204   bench_all_modes(bench_parmap_full, nthreads, modes);
205   printf("\n");
206
207   printf("Benchmark for parmap apply only (big comp):\n");
208   bench_all_modes(bench_parmap_apply, nthreads, modes);
209   printf("\n");
210
211   return EXIT_SUCCESS;
212 }