Logo AND Algorithmique Numérique Distribuée

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