Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
b9d6366c8d9c0dc7adb24e635efe75dfc1f56b19
[simgrid.git] / src / smpi / smpi_bench.c
1 /* Copyright (c) 2007, 2009, 2010. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5   * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include "private.h"
8 #include "xbt/dict.h"
9 #include "xbt/sysdep.h"
10 #include "xbt/ex.h"
11 #include "surf/surf.h"
12
13 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_bench, smpi,
14                                 "Logging specific to SMPI (benchmarking)");
15
16 xbt_dict_t allocs = NULL;       /* Allocated on first use */
17 xbt_dict_t samples = NULL;      /* Allocated on first use */
18 xbt_dict_t calls = NULL;        /* Allocated on first use */
19 __thread int smpi_current_rank = 0;      /* Updated after each MPI call */
20
21 typedef struct {
22   int count;
23   char data[];
24 } shared_data_t;
25
26 typedef struct {
27   int count;
28   double sum;
29   double sum_pow2;
30   double mean;
31   double relstderr;
32   int iters;
33   double threshold;
34   int started;
35 } local_data_t;
36
37 void smpi_bench_destroy(void)
38 {
39   if (allocs) {
40     xbt_dict_free(&allocs);
41   }
42   if (samples) {
43     xbt_dict_free(&samples);
44   }
45   if(calls) {
46     xbt_dict_free(&calls);
47   }
48 }
49
50 static void smpi_execute_flops(double flops)
51 {
52   smx_action_t action;
53   smx_host_t host;
54   host = SIMIX_host_self();
55
56   XBT_DEBUG("Handle real computation time: %f flops", flops);
57   action = SIMIX_req_host_execute("computation", host, flops, 1);
58 #ifdef HAVE_TRACING
59   SIMIX_req_set_category (action, TRACE_internal_smpi_get_category());
60 #endif
61   SIMIX_req_host_execution_wait(action);
62 }
63
64 static void smpi_execute(double duration)
65 {
66   if (duration >= xbt_cfg_get_double(_surf_cfg_set, "smpi/cpu_threshold")) {
67     XBT_DEBUG("Sleep for %f to handle real computation time", duration);
68     smpi_execute_flops(duration *
69                        xbt_cfg_get_double(_surf_cfg_set,
70                                           "smpi/running_power"));
71   }
72 }
73
74 void smpi_bench_begin(void)
75 {
76   xbt_os_timer_start(smpi_process_timer());
77   smpi_current_rank = smpi_process_index();
78 }
79
80 void smpi_bench_end(void)
81 {
82   xbt_os_timer_t timer = smpi_process_timer();
83
84   xbt_os_timer_stop(timer);
85   smpi_execute(xbt_os_timer_elapsed(timer));
86 }
87
88 unsigned int smpi_sleep(unsigned int secs)
89 {
90   smpi_execute((double) secs);
91   return secs;
92 }
93
94 int smpi_gettimeofday(struct timeval *tv, struct timezone *tz)
95 {
96   double now = SIMIX_get_clock();
97
98   if (tv) {
99     tv->tv_sec = (time_t) now;
100     tv->tv_usec = (suseconds_t) (now * 1e6);
101   }
102   return 0;
103 }
104
105 static char *sample_location(int global, const char *file, int line)
106 {
107   if (global) {
108     return bprintf("%s:%d", file, line);
109   } else {
110     return bprintf("%s:%d:%d", file, line, smpi_process_index());
111   }
112 }
113
114 int smpi_sample_1(int global, const char *file, int line, int iters, double threshold)
115 {
116   char *loc = sample_location(global, file, line);
117   local_data_t *data;
118
119   smpi_bench_end();     /* Take time from previous MPI call into account */
120   if (!samples) {
121     samples = xbt_dict_new();
122   }
123   data = xbt_dict_get_or_null(samples, loc);
124   if (!data) {
125     data = (local_data_t *) xbt_new(local_data_t, 1);
126     data->count = 0;
127     data->sum = 0.0;
128     data->sum_pow2 = 0.0;
129     data->iters = iters;
130     data->threshold = threshold;
131     data->started = 0;
132     xbt_dict_set(samples, loc, data, &free);
133     return 0;
134   }
135   free(loc);
136   return 1;
137 }
138
139 int smpi_sample_2(int global, const char *file, int line)
140 {
141   char *loc = sample_location(global, file, line);
142   local_data_t *data;
143
144   xbt_assert(samples, "You did something very inconsistent, didn't you?");
145   data = xbt_dict_get_or_null(samples, loc);
146   if (!data) {
147     xbt_assert(data, "Please, do thing in order");
148   }
149   if (!data->started) {
150     if ((data->iters > 0 && data->count >= data->iters)
151         || (data->count > 1 && data->threshold > 0.0 && data->relstderr <= data->threshold)) {
152       XBT_DEBUG("Perform some wait of %f", data->mean);
153       smpi_execute(data->mean);
154     } else {
155       data->started = 1;
156       data->count++;
157     }
158   } else {
159     data->started = 0;
160   }
161   free(loc);
162   smpi_bench_begin();
163   smpi_process_simulated_start();
164   return data->started;
165 }
166
167 void smpi_sample_3(int global, const char *file, int line)
168 {
169   char *loc = sample_location(global, file, line);
170   local_data_t *data;
171   double sample, n;
172
173   xbt_assert(samples, "You did something very inconsistent, didn't you?");
174   data = xbt_dict_get_or_null(samples, loc);
175   smpi_bench_end();
176   if(data && data->started && data->count < data->iters) {
177     sample = smpi_process_simulated_elapsed();
178     data->sum += sample;
179     data->sum_pow2 += sample * sample;
180     n = (double)data->count;
181     data->mean = data->sum / n;
182     data->relstderr = sqrt((data->sum_pow2 / n - data->mean * data->mean) / n) / data->mean;
183     XBT_DEBUG("Average mean after %d steps is %f, relative standard error is %f (sample was %f)", data->count,
184            data->mean, data->relstderr, sample);
185   }
186   free(loc);
187 }
188
189 void smpi_sample_flops(double flops)
190 {
191   smpi_execute_flops(flops);
192 }
193
194 void *smpi_shared_malloc(size_t size, const char *file, int line)
195 {
196   char *loc = bprintf("%s:%d:%zu", file, line, size);
197   shared_data_t *data;
198
199   if (!allocs) {
200     allocs = xbt_dict_new();
201   }
202   data = xbt_dict_get_or_null(allocs, loc);
203   if (!data) {
204     data = (shared_data_t *) xbt_malloc0(sizeof(int) + size);
205     data->count = 1;
206     xbt_dict_set(allocs, loc, data, &free);
207   } else {
208     data->count++;
209   }
210   free(loc);
211   return data->data;
212 }
213
214 void smpi_shared_free(void *ptr)
215 {
216   shared_data_t *data = (shared_data_t *) ((int *) ptr - 1);
217   char *loc;
218
219   if (!allocs) {
220     XBT_WARN("Cannot free: nothing was allocated");
221     return;
222   }
223   loc = xbt_dict_get_key(allocs, data);
224   if (!loc) {
225     XBT_WARN("Cannot free: %p was not shared-allocated by SMPI", ptr);
226     return;
227   }
228   data->count--;
229   if (data->count <= 0) {
230     xbt_dict_remove(allocs, loc);
231   }
232 }
233
234 int smpi_shared_known_call(const char* func, const char* input) {
235    char* loc = bprintf("%s:%s", func, input);
236    xbt_ex_t ex;
237    int known;
238
239    if(!calls) {
240       calls = xbt_dict_new();
241    }
242    TRY {
243       xbt_dict_get(calls, loc); /* Succeed or throw */
244       known = 1;
245    } CATCH(ex) {
246       if(ex.category == not_found_error) {
247          known = 0;
248          xbt_ex_free(ex);
249       } else {
250          RETHROW;
251       }
252    }
253    free(loc);
254    return known;
255 }
256
257 void* smpi_shared_get_call(const char* func, const char* input) {
258    char* loc = bprintf("%s:%s", func, input);
259    void* data;
260
261    if(!calls) {
262       calls = xbt_dict_new();
263    }
264    data = xbt_dict_get(calls, loc);
265    free(loc);
266    return data;
267 }
268
269 void* smpi_shared_set_call(const char* func, const char* input, void* data) {
270    char* loc = bprintf("%s:%s", func, input);
271
272    if(!calls) {
273       calls = xbt_dict_new();
274    }
275    xbt_dict_set(calls, loc, data, NULL);
276    free(loc);
277    return data;
278 }