~ubuntu-branches/ubuntu/raring/simgrid/raring

« back to all changes in this revision

Viewing changes to src/smpi/smpi_bench.c

  • Committer: Package Import Robot
  • Author(s): Martin Quinson
  • Date: 2013-01-31 00:24:51 UTC
  • mfrom: (10.1.6 sid)
  • Revision ID: package-import@ubuntu.com-20130131002451-krejhf7w7h24lpsc
Tags: 3.9~rc1-1
* New upstream release: the "Grasgory" release. Major changes:
  - Gras was completely removed from this version.
  - Documentation reorganization to ease browsing it.
  - New default value for the TCP_gamma parameter: 4MiB

Show diffs side-by-side

added added

removed removed

Lines of Context:
4
4
/* This program is free software; you can redistribute it and/or modify it
5
5
  * under the terms of the license (GNU LGPL) which comes with this package. */
6
6
 
7
 
#include <math.h> // sqrt
8
7
#include "private.h"
9
8
#include "xbt/dict.h"
10
9
#include "xbt/sysdep.h"
11
10
#include "xbt/ex.h"
12
11
#include "surf/surf.h"
 
12
#include "simgrid/sg_config.h"
13
13
 
 
14
#ifndef WIN32
14
15
#include <sys/mman.h>
 
16
#endif
15
17
#include <sys/stat.h>
16
18
#include <sys/types.h>
17
19
#include <errno.h>
18
20
#include <fcntl.h>
 
21
#include <math.h> // sqrt
19
22
#include <unistd.h>
20
23
#include <string.h>
21
24
#include <stdio.h>
82
85
  return (size_t)st.st_size;
83
86
}
84
87
 
 
88
#ifndef WIN32
85
89
static void* shm_map(int fd, size_t size, shared_data_t* data) {
86
90
  void* mem;
87
91
  char loc[PTR_STRLEN];
92
96
      xbt_die("Could not truncate fd %d to %zu: %s", fd, size, strerror(errno));
93
97
    }
94
98
  }
 
99
 
95
100
  mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
96
101
  if(mem == MAP_FAILED) {
97
102
    xbt_die("Could not map fd %d: %s", fd, strerror(errno));
107
112
  XBT_DEBUG("MMAP %zu to %p", size, mem);
108
113
  return mem;
109
114
}
110
 
 
111
 
typedef struct {
112
 
  int count;
113
 
  double sum;
114
 
  double sum_pow2;
115
 
  double mean;
116
 
  double relstderr;
117
 
  int iters;
118
 
  double threshold;
119
 
  int started;
120
 
} local_data_t;
 
115
#endif
121
116
 
122
117
void smpi_bench_destroy(void)
123
118
{
126
121
  xbt_dict_free(&calls);
127
122
}
128
123
 
129
 
static void smpi_execute_flops(double flops)
130
 
{
 
124
void smpi_execute_flops(double flops) {
131
125
  smx_action_t action;
132
126
  smx_host_t host;
133
127
  host = SIMIX_host_self();
143
137
static void smpi_execute(double duration)
144
138
{
145
139
  /* FIXME: a global variable would be less expensive to consult than a call to xbt_cfg_get_double() right on the critical path */
146
 
  if (duration >= xbt_cfg_get_double(_surf_cfg_set, "smpi/cpu_threshold")) {
 
140
  if (duration >= sg_cfg_get_double("smpi/cpu_threshold")) {
147
141
    XBT_DEBUG("Sleep for %f to handle real computation time", duration);
148
142
    smpi_execute_flops(duration *
149
 
                       xbt_cfg_get_double(_surf_cfg_set,
150
 
                                          "smpi/running_power"));
 
143
                sg_cfg_get_double("smpi/running_power"));
151
144
  } else {
152
 
          XBT_DEBUG("Real computation took %f while threshold is set to %f; ignore it",
153
 
                          duration, xbt_cfg_get_double(_surf_cfg_set, "smpi/cpu_threshold"));
 
145
    XBT_DEBUG("Real computation took %f while option smpi/cpu_threshold is set to %f => ignore it",
 
146
        duration, sg_cfg_get_double("smpi/cpu_threshold"));
154
147
  }
155
148
}
156
149
 
176
169
  return secs;
177
170
}
178
171
 
179
 
int smpi_gettimeofday(struct timeval *tv, struct timezone *tz)
 
172
int smpi_gettimeofday(struct timeval *tv)
180
173
{
181
174
  double now;
182
175
  smpi_bench_end();
183
176
  now = SIMIX_get_clock();
184
177
  if (tv) {
185
178
    tv->tv_sec = (time_t)now;
 
179
#ifdef WIN32
 
180
    tv->tv_usec = (useconds_t)((now - tv->tv_sec) * 1e6);
 
181
#else
186
182
    tv->tv_usec = (suseconds_t)((now - tv->tv_sec) * 1e6);
 
183
#endif
187
184
  }
188
185
  smpi_bench_begin();
189
186
  return 0;
209
206
  return (unsigned long long)sec * smpi_rastro_resolution() + pre;
210
207
}
211
208
 
212
 
static char *sample_location(int global, const char *file, int line)
213
 
{
 
209
/* ****************************** Functions related to the SMPI_SAMPLE_ macros ************************************/
 
210
typedef struct {
 
211
  int iters;        /* amount of requested iterations */
 
212
  int count;        /* amount of iterations done so far */
 
213
  double threshold; /* maximal stderr requested (if positive) */
 
214
  double relstderr; /* observed stderr so far */
 
215
  double mean;      /* mean of benched times, to be used if the block is disabled */
 
216
  double sum;       /* sum of benched times (to compute the mean and stderr) */
 
217
  double sum_pow2;  /* sum of the square of the benched times (to compute the stderr) */
 
218
  int benching;     /* 1: we are benchmarking; 0: we have enough data, no bench anymore */
 
219
} local_data_t;
 
220
 
 
221
static char *sample_location(int global, const char *file, int line) {
214
222
  if (global) {
215
223
    return bprintf("%s:%d", file, line);
216
224
  } else {
217
225
    return bprintf("%s:%d:%d", file, line, smpi_process_index());
218
226
  }
219
227
}
 
228
static int sample_enough_benchs(local_data_t *data) {
 
229
  int res = data->count >= data->iters;
 
230
  if (data->threshold>0.0) {
 
231
    if (data->count <2)
 
232
      res = 0; // not enough data
 
233
    if (data->relstderr > data->threshold)
 
234
      res = 0; // stderr too high yet
 
235
  }
 
236
  XBT_DEBUG("%s (count:%d iter:%d stderr:%f thres:%f mean:%fs)",
 
237
      (res?"enough benchs":"need more data"),
 
238
      data->count, data->iters, data->relstderr, data->threshold, data->mean);
 
239
  return res;
 
240
}
220
241
 
221
 
int smpi_sample_1(int global, const char *file, int line, int iters, double threshold)
 
242
void smpi_sample_1(int global, const char *file, int line, int iters, double threshold)
222
243
{
223
244
  char *loc = sample_location(global, file, line);
224
245
  local_data_t *data;
225
246
 
226
 
  smpi_bench_end();     /* Take time from previous MPI call into account */
227
 
  if (!samples) {
 
247
  smpi_bench_end();     /* Take time from previous, unrelated computation into account */
 
248
  if (!samples)
228
249
    samples = xbt_dict_new_homogeneous(free);
229
 
  }
 
250
 
230
251
  data = xbt_dict_get_or_null(samples, loc);
231
252
  if (!data) {
 
253
    xbt_assert(threshold>0 || iters>0,
 
254
        "You should provide either a positive amount of iterations to bench, or a positive maximal stderr (or both)");
232
255
    data = (local_data_t *) xbt_new(local_data_t, 1);
233
256
    data->count = 0;
234
257
    data->sum = 0.0;
235
258
    data->sum_pow2 = 0.0;
236
259
    data->iters = iters;
237
260
    data->threshold = threshold;
238
 
    data->started = 0;
 
261
    data->benching = 1; // If we have no data, we need at least one
 
262
    data->mean = 0;
239
263
    xbt_dict_set(samples, loc, data, NULL);
 
264
    XBT_DEBUG("XXXXX First time ever on benched nest %s.",loc);
 
265
  } else {
 
266
    if (data->iters != iters || data->threshold != threshold) {
 
267
      XBT_ERROR("Asked to bench block %s with different settings %d, %f is not %d, %f. How did you manage to give two numbers at the same line??",
 
268
          loc, data->iters, data->threshold, iters,threshold);
 
269
      THROW_IMPOSSIBLE;
 
270
    }
 
271
 
 
272
    // if we already have some data, check whether sample_2 should get one more bench or whether it should emulate the computation instead
 
273
    data->benching = !sample_enough_benchs(data);
 
274
    XBT_DEBUG("XXXX Re-entering the benched nest %s. %s",loc, (data->benching?"more benching needed":"we have enough data, skip computes"));
 
275
  }
 
276
  free(loc);
 
277
}
 
278
 
 
279
int smpi_sample_2(int global, const char *file, int line)
 
280
{
 
281
  char *loc = sample_location(global, file, line);
 
282
  local_data_t *data;
 
283
 
 
284
  xbt_assert(samples, "Y U NO use SMPI_SAMPLE_* macros? Stop messing directly with smpi_sample_* functions!");
 
285
  data = xbt_dict_get(samples, loc);
 
286
  XBT_DEBUG("sample2 %s",loc);
 
287
  free(loc);
 
288
 
 
289
  if (data->benching==1) {
 
290
    // we need to run a new bench
 
291
    XBT_DEBUG("benchmarking: count:%d iter:%d stderr:%f thres:%f; mean:%f",
 
292
        data->count, data->iters, data->relstderr, data->threshold, data->mean);
 
293
    smpi_bench_begin();
 
294
    return 1;
 
295
  } else {
 
296
    // Enough data, no more bench (either we got enough data from previous visits to this benched nest, or we just ran one bench and need to bail out now that our job is done).
 
297
    // Just sleep instead
 
298
    XBT_DEBUG("No benchmark (either no need, or just ran one): count >= iter (%d >= %d) or stderr<thres (%f<=%f). apply the %fs delay instead",
 
299
        data->count, data->iters, data->relstderr, data->threshold, data->mean);
 
300
    smpi_execute(data->mean);
 
301
 
 
302
    smpi_bench_begin(); // prepare to capture future, unrelated computations
240
303
    return 0;
241
304
  }
242
 
  free(loc);
243
 
  return 1;
244
 
}
245
 
 
246
 
int smpi_sample_2(int global, const char *file, int line)
247
 
{
248
 
  char *loc = sample_location(global, file, line);
249
 
  local_data_t *data;
250
 
 
251
 
  xbt_assert(samples, "You did something very inconsistent, didn't you?");
252
 
  data = xbt_dict_get_or_null(samples, loc);
253
 
  if (!data) {
254
 
    xbt_assert(data, "Please, do thing in order");
255
 
  }
256
 
  if (!data->started) {
257
 
    if ((data->iters > 0 && data->count >= data->iters)
258
 
        || (data->count > 1 && data->threshold > 0.0 && data->relstderr <= data->threshold)) {
259
 
      XBT_DEBUG("Perform some wait of %f", data->mean);
260
 
      smpi_execute(data->mean);
261
 
    } else {
262
 
      data->started = 1;
263
 
      data->count++;
264
 
    }
265
 
  } else {
266
 
    data->started = 0;
267
 
  }
268
 
  free(loc);
269
 
  smpi_bench_begin();
270
 
  smpi_process_simulated_start();
271
 
  return data->started;
272
 
}
 
305
}
 
306
 
273
307
 
274
308
void smpi_sample_3(int global, const char *file, int line)
275
309
{
276
310
  char *loc = sample_location(global, file, line);
277
311
  local_data_t *data;
 
312
 
 
313
  xbt_assert(samples, "Y U NO use SMPI_SAMPLE_* macros? Stop messing directly with smpi_sample_* functions!");
 
314
  data = xbt_dict_get(samples, loc);
 
315
  XBT_DEBUG("sample3 %s",loc);
 
316
 
 
317
  if (data->benching==0) {
 
318
    THROW_IMPOSSIBLE;
 
319
  }
 
320
 
 
321
  // ok, benchmarking this loop is over
 
322
  xbt_os_timer_stop(smpi_process_timer());
 
323
 
 
324
  // update the stats
278
325
  double sample, n;
279
 
 
280
 
  xbt_assert(samples, "You did something very inconsistent, didn't you?");
281
 
  data = xbt_dict_get_or_null(samples, loc);
282
 
  smpi_bench_end();
283
 
  if(data && data->started && data->count < data->iters) {
284
 
    sample = smpi_process_simulated_elapsed();
285
 
    data->sum += sample;
286
 
    data->sum_pow2 += sample * sample;
287
 
    n = (double)data->count;
288
 
    data->mean = data->sum / n;
289
 
    data->relstderr = sqrt((data->sum_pow2 / n - data->mean * data->mean) / n) / data->mean;
290
 
    XBT_DEBUG("Average mean after %d steps is %f, relative standard error is %f (sample was %f)", data->count,
291
 
           data->mean, data->relstderr, sample);
 
326
  data->count++;
 
327
  sample = xbt_os_timer_elapsed(smpi_process_timer());
 
328
  data->sum += sample;
 
329
  data->sum_pow2 += sample * sample;
 
330
  n = (double)data->count;
 
331
  data->mean = data->sum / n;
 
332
  data->relstderr = sqrt((data->sum_pow2 / n - data->mean * data->mean) / n) / data->mean;
 
333
  if (!sample_enough_benchs(data)) {
 
334
    data->mean = sample; // Still in benching process; We want sample_2 to simulate the exact time of this loop occurrence before leaving, not the mean over the history
292
335
  }
293
 
  free(loc);
294
 
}
295
 
 
296
 
void smpi_sample_flops(double flops)
297
 
{
298
 
  smpi_execute_flops(flops);
299
 
}
300
 
 
 
336
  XBT_DEBUG("Average mean after %d steps is %f, relative standard error is %f (sample was %f)", data->count,
 
337
      data->mean, data->relstderr, sample);
 
338
 
 
339
  // That's enough for now, prevent sample_2 to run the same code over and over
 
340
  data->benching = 0;
 
341
}
 
342
 
 
343
#ifndef WIN32
301
344
void *smpi_shared_malloc(size_t size, const char *file, int line)
302
345
{
303
346
  char *loc = bprintf("%zu_%s_%d", (size_t)getpid(), file, line);
344
387
  XBT_DEBUG("Malloc %zu in %p (metadata at %p)", size, mem, data);
345
388
  return mem;
346
389
}
347
 
 
348
390
void smpi_shared_free(void *ptr)
349
391
{
350
392
  char loc[PTR_STRLEN];
379
421
    free(data->loc);
380
422
  }
381
423
}
 
424
#endif
382
425
 
383
426
int smpi_shared_known_call(const char* func, const char* input) {
384
427
   char* loc = bprintf("%s:%s", func, input);