Logo AND Algorithmique Numérique Distribuée

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