Logo AND Algorithmique Numérique Distribuée

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