1 /* Copyright (c) 2012-2017. The SimGrid Team. All rights reserved. */
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. */
6 #include "simgrid/msg.h"
7 #include "src/internal_config.h" /* HAVE_FUTEX_H */
8 #include "xbt/xbt_os_time.h"
11 #include <xbt/dynar.h>
12 #include <xbt/parmap.h>
13 #include <xbt/sysdep.h>
15 #define MODES_DEFAULT 0x7
17 #define ARRAY_SIZE 10007
20 void (*fun_to_apply)(void *);
22 static const char *parmap_mode_name(e_xbt_parmap_mode_t mode)
26 case XBT_PARMAP_POSIX:
27 snprintf(name, sizeof name, "POSIX");
29 case XBT_PARMAP_FUTEX:
30 snprintf(name, sizeof name, "FUTEX");
32 case XBT_PARMAP_BUSY_WAIT:
33 snprintf(name, sizeof name, "BUSY_WAIT");
35 case XBT_PARMAP_DEFAULT:
36 snprintf(name, sizeof name, "DEFAULT");
39 snprintf(name, sizeof name, "UNKNOWN(%d)", (int)mode);
45 static int parmap_skip_mode(e_xbt_parmap_mode_t mode)
48 if (mode == XBT_PARMAP_FUTEX) {
49 printf("not available\n");
56 static unsigned fibonacci(unsigned n)
61 return fibonacci(n - 1) + fibonacci(n - 2);
64 static void fun_small_comp(void *arg)
70 static void fun_big_comp(void *arg)
73 *u = fibonacci(*u % FIBO_MAX);
76 static void array_new(unsigned **a, xbt_dynar_t *data)
78 *a = xbt_malloc(ARRAY_SIZE * sizeof **a);
79 *data = xbt_dynar_new(sizeof *a, NULL);
80 xbt_dynar_shrink(*data, ARRAY_SIZE);
81 for (int i = 0 ; i < ARRAY_SIZE ; i++) {
83 xbt_dynar_push_as(*data, void*, &(*a)[i]);
87 static void bench_parmap_full(int nthreads, e_xbt_parmap_mode_t mode)
94 printf("** mode = %-15s ", parmap_mode_name(mode));
97 if (parmap_skip_mode(mode))
100 array_new(&a, &data);
103 double start_time = xbt_os_time();
105 parmap = xbt_parmap_new(nthreads, mode);
106 xbt_parmap_apply(parmap, fun_to_apply, data);
107 xbt_parmap_destroy(parmap);
108 elapsed_time = xbt_os_time() - start_time;
110 } while (elapsed_time < TIMEOUT);
112 printf("ran %d times in %g seconds (%g/s)\n", i, elapsed_time, i / elapsed_time);
114 xbt_dynar_free(&data);
118 static void bench_parmap_apply(int nthreads, e_xbt_parmap_mode_t mode)
124 printf("** mode = %-15s ", parmap_mode_name(mode));
127 if (parmap_skip_mode(mode))
130 array_new(&a, &data);
132 xbt_parmap_t parmap = xbt_parmap_new(nthreads, mode);
134 double start_time = xbt_os_time();
136 xbt_parmap_apply(parmap, fun_to_apply, data);
137 elapsed_time = xbt_os_time() - start_time;
139 } while (elapsed_time < TIMEOUT);
140 xbt_parmap_destroy(parmap);
142 printf("ran %d times in %g seconds (%g/s)\n", i, elapsed_time, i / elapsed_time);
144 xbt_dynar_free(&data);
148 static void bench_all_modes(void (*bench_fun)(int, e_xbt_parmap_mode_t),
149 int nthreads, unsigned modes)
151 e_xbt_parmap_mode_t all_modes[] = {XBT_PARMAP_POSIX, XBT_PARMAP_FUTEX, XBT_PARMAP_BUSY_WAIT, XBT_PARMAP_DEFAULT};
153 for (unsigned i = 0 ; i < sizeof all_modes / sizeof all_modes[0] ; i++) {
155 bench_fun(nthreads, all_modes[i]);
159 int main(int argc, char *argv[])
162 unsigned modes = MODES_DEFAULT;
164 MSG_init(&argc, argv);
166 if (argc != 2 && argc != 3) {
167 fprintf(stderr, "Usage: %s nthreads [modes]\n"
168 " nthreads - number of working threads\n"
169 " modes - bitmask of modes to test\n",
173 nthreads = atoi(argv[1]);
175 fprintf(stderr, "ERROR: invalid thread count: %d\n", nthreads);
179 modes = strtol(argv[2], NULL, 0);
181 printf("Parmap benchmark with %d workers (modes = %#x)...\n\n", nthreads, modes);
183 fun_to_apply = &fun_small_comp;
185 printf("Benchmark for parmap create+apply+destroy (small comp):\n");
186 bench_all_modes(bench_parmap_full, nthreads, modes);
189 printf("Benchmark for parmap apply only (small comp):\n");
190 bench_all_modes(bench_parmap_apply, nthreads, modes);
193 fun_to_apply = &fun_big_comp;
195 printf("Benchmark for parmap create+apply+destroy (big comp):\n");
196 bench_all_modes(bench_parmap_full, nthreads, modes);
199 printf("Benchmark for parmap apply only (big comp):\n");
200 bench_all_modes(bench_parmap_apply, nthreads, modes);