Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
This should be a per process variable.
[simgrid.git] / src / smpi / smpi_bench.c
index 357e6f8..3992750 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007, 2009, 2010. The SimGrid Team.
+/* Copyright (c) 2007, 2009-2013. The SimGrid Team.
  * All rights reserved.                                                     */
 
 /* This program is free software; you can redistribute it and/or modify it
@@ -8,6 +8,7 @@
 #include "xbt/dict.h"
 #include "xbt/sysdep.h"
 #include "xbt/ex.h"
+#include "xbt/hash.h"
 #include "surf/surf.h"
 #include "simgrid/sg_config.h"
 
@@ -65,6 +66,9 @@ xbt_dict_t samples = NULL;         /* Allocated on first use */
 xbt_dict_t calls = NULL;           /* Allocated on first use */
 __thread int smpi_current_rank = 0;      /* Updated after each MPI call */
 
+double smpi_cpu_threshold;
+double smpi_running_power;
+
 typedef struct {
   int fd;
   int count;
@@ -102,13 +106,13 @@ static void* shm_map(int fd, size_t size, shared_data_t* data) {
     xbt_die("Could not map fd %d: %s", fd, strerror(errno));
   }
   if(!allocs_metadata) {
-    allocs_metadata = xbt_dict_new();
+    allocs_metadata = xbt_dict_new_homogeneous(xbt_free);
   }
   snprintf(loc, PTR_STRLEN, "%p", mem);
   meta = xbt_new(shared_metadata_t, 1);
   meta->size = size;
   meta->data = data;
-  xbt_dict_set(allocs_metadata, loc, meta, &free);
+  xbt_dict_set(allocs_metadata, loc, meta, NULL);
   XBT_DEBUG("MMAP %zu to %p", size, mem);
   return mem;
 }
@@ -117,6 +121,7 @@ static void* shm_map(int fd, size_t size, shared_data_t* data) {
 void smpi_bench_destroy(void)
 {
   xbt_dict_free(&allocs);
+  xbt_dict_free(&allocs_metadata);
   xbt_dict_free(&samples);
   xbt_dict_free(&calls);
 }
@@ -125,8 +130,7 @@ void smpi_execute_flops(double flops) {
   smx_action_t action;
   smx_host_t host;
   host = SIMIX_host_self();
-
-  XBT_DEBUG("Handle real computation time: %f flops", flops);
+  XBT_DEBUG("Handle real computation time: %g flops", flops);
   action = simcall_host_execute("computation", host, flops, 1);
 #ifdef HAVE_TRACING
   simcall_set_category (action, TRACE_internal_smpi_get_category());
@@ -136,14 +140,25 @@ void smpi_execute_flops(double flops) {
 
 static void smpi_execute(double duration)
 {
-  /* FIXME: a global variable would be less expensive to consult than a call to xbt_cfg_get_double() right on the critical path */
-  if (duration >= sg_cfg_get_double("smpi/cpu_threshold")) {
-    XBT_DEBUG("Sleep for %f to handle real computation time", duration);
-    smpi_execute_flops(duration *
-               sg_cfg_get_double("smpi/running_power"));
+  if (duration >= smpi_cpu_threshold) {
+    XBT_DEBUG("Sleep for %g to handle real computation time", duration);
+    double flops = duration * smpi_running_power;
+#ifdef HAVE_TRACING
+    int rank = smpi_process_index();
+    instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
+    extra->type=TRACING_COMPUTING;
+    extra->comp_size=flops;
+    TRACE_smpi_computing_in(rank, extra);
+#endif
+    smpi_execute_flops(flops);
+
+#ifdef HAVE_TRACING
+    TRACE_smpi_computing_out(rank);
+#endif
+
   } else {
-    XBT_DEBUG("Real computation took %f while option smpi/cpu_threshold is set to %f => ignore it",
-        duration, sg_cfg_get_double("smpi/cpu_threshold"));
+    XBT_DEBUG("Real computation took %g while option smpi/cpu_threshold is set to %g => ignore it",
+              duration, smpi_cpu_threshold);
   }
 }
 
@@ -163,8 +178,18 @@ void smpi_bench_end(void)
 
 unsigned int smpi_sleep(unsigned int secs)
 {
+  smx_action_t action;
+
   smpi_bench_end();
-  smpi_execute((double) secs);
+
+  double flops = (double) secs*simcall_host_get_speed(SIMIX_host_self());
+  XBT_DEBUG("Sleep for: %f flops", flops);
+  action = simcall_host_execute("computation", SIMIX_host_self(), flops, 1);
+  #ifdef HAVE_TRACING
+    simcall_set_category (action, TRACE_internal_smpi_get_category());
+  #endif
+  simcall_host_execution_wait(action);
+
   smpi_bench_begin();
   return secs;
 }
@@ -208,13 +233,13 @@ unsigned long long smpi_rastro_timestamp (void)
 
 /* ****************************** Functions related to the SMPI_SAMPLE_ macros ************************************/
 typedef struct {
-  int iters;        /* amount of requested iterations */
-  int count;        /* amount of iterations done so far */
   double threshold; /* maximal stderr requested (if positive) */
   double relstderr; /* observed stderr so far */
   double mean;      /* mean of benched times, to be used if the block is disabled */
   double sum;       /* sum of benched times (to compute the mean and stderr) */
   double sum_pow2;  /* sum of the square of the benched times (to compute the stderr) */
+  int iters;        /* amount of requested iterations */
+  int count;        /* amount of iterations done so far */
   int benching;     /* 1: we are benchmarking; 0: we have enough data, no bench anymore */
 } local_data_t;
 
@@ -245,6 +270,8 @@ void smpi_sample_1(int global, const char *file, int line, int iters, double thr
   local_data_t *data;
 
   smpi_bench_end();     /* Take time from previous, unrelated computation into account */
+  smpi_process_set_sampling(1);
+
   if (!samples)
     samples = xbt_dict_new_homogeneous(free);
 
@@ -280,6 +307,7 @@ int smpi_sample_2(int global, const char *file, int line)
 {
   char *loc = sample_location(global, file, line);
   local_data_t *data;
+  int res;
 
   xbt_assert(samples, "Y U NO use SMPI_SAMPLE_* macros? Stop messing directly with smpi_sample_* functions!");
   data = xbt_dict_get(samples, loc);
@@ -290,18 +318,18 @@ int smpi_sample_2(int global, const char *file, int line)
     // we need to run a new bench
     XBT_DEBUG("benchmarking: count:%d iter:%d stderr:%f thres:%f; mean:%f",
         data->count, data->iters, data->relstderr, data->threshold, data->mean);
-    smpi_bench_begin();
-    return 1;
+    res = 1;
   } else {
     // 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).
     // Just sleep instead
     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",
         data->count, data->iters, data->relstderr, data->threshold, data->mean);
     smpi_execute(data->mean);
-
-    smpi_bench_begin(); // prepare to capture future, unrelated computations
-    return 0;
+    smpi_process_set_sampling(0);
+    res = 0; // prepare to capture future, unrelated computations
   }
+  smpi_bench_begin();
+  return res;
 }
 
 
@@ -342,50 +370,83 @@ void smpi_sample_3(int global, const char *file, int line)
 }
 
 #ifndef WIN32
-void *smpi_shared_malloc(size_t size, const char *file, int line)
+static void smpi_shared_alloc_free(void *p)
 {
-  char *loc = bprintf("%zu_%s_%d", (size_t)getpid(), file, line);
-  size_t len = strlen(loc);
-  size_t i;
-  int fd;
-  void* mem;
-  shared_data_t *data;
+  shared_data_t *data = p;
+  xbt_free(data->loc);
+  xbt_free(data);
+}
 
-  for(i = 0; i < len; i++) {
-    /* Make the 'loc' ID be a flat filename */
-    if(loc[i] == '/') {
-      loc[i] = '_';
+static char *smpi_shared_alloc_hash(char *loc)
+{
+  char hash[42];
+  char s[7];
+  unsigned val;
+  int i, j;
+
+  xbt_sha(loc, hash);
+  hash[41] = '\0';
+  s[6] = '\0';
+  loc = xbt_realloc(loc, 30);
+  loc[0] = '/';
+  for (i = 0; i < 40; i += 6) { /* base64 encode */
+    memcpy(s, hash + i, 6);
+    val = strtoul(s, NULL, 16);
+    for (j = 0; j < 4; j++) {
+      unsigned char x = (val >> (18 - 3 * j)) & 0x3f;
+      loc[1 + 4 * i / 6 + j] =
+        "ABCDEFGHIJKLMNOPQRSTUVZXYZabcdefghijklmnopqrstuvzxyz0123456789-_"[x];
     }
   }
-  if (!allocs) {
-    allocs = xbt_dict_new_homogeneous(free);
-  }
-  data = xbt_dict_get_or_null(allocs, loc);
-  if(!data) {
-    fd = shm_open(loc, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-    if(fd < 0) {
-      switch(errno) {
-        case EEXIST:
-          xbt_die("Please cleanup /dev/shm/%s", loc);
-        default:
-          xbt_die("An unhandled error occured while opening %s: %s", loc, strerror(errno));
-      }
+  loc[29] = '\0';
+  return loc;
+}
+
+void *smpi_shared_malloc(size_t size, const char *file, int line)
+{
+  void* mem;
+  if (sg_cfg_get_boolean("smpi/use_shared_malloc")){
+    char *loc = bprintf("%zu_%s_%d", (size_t)getpid(), file, line);
+    int fd;
+    shared_data_t *data;
+    loc = smpi_shared_alloc_hash(loc); /* hash loc, in order to have something
+                                        * not too long */
+    if (!allocs) {
+      allocs = xbt_dict_new_homogeneous(smpi_shared_alloc_free);
     }
-    data = xbt_new(shared_data_t, 1);
-    data->fd = fd;
-    data->count = 1;
-    data->loc = loc;
-    mem = shm_map(fd, size, data);
-    if(shm_unlink(loc) < 0) {
-      XBT_WARN("Could not early unlink %s: %s", loc, strerror(errno));
+    data = xbt_dict_get_or_null(allocs, loc);
+    if (!data) {
+      fd = shm_open(loc, O_RDWR | O_CREAT | O_EXCL,
+                    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+      if (fd < 0) {
+        switch(errno) {
+          case EEXIST:
+            xbt_die("Please cleanup /dev/shm/%s", loc);
+          default:
+            xbt_die("An unhandled error occured while opening %s. shm_open: %s", loc, strerror(errno));
+        }
+      }
+      data = xbt_new(shared_data_t, 1);
+      data->fd = fd;
+      data->count = 1;
+      data->loc = loc;
+      mem = shm_map(fd, size, data);
+      if (shm_unlink(loc) < 0) {
+        XBT_WARN("Could not early unlink %s. shm_unlink: %s", loc, strerror(errno));
+      }
+      xbt_dict_set(allocs, loc, data, NULL);
+      XBT_DEBUG("Mapping %s at %p through %d", loc, mem, fd);
+    } else {
+      xbt_free(loc);
+      mem = shm_map(data->fd, size, data);
+      data->count++;
     }
-    xbt_dict_set(allocs, loc, data, NULL);
-    XBT_DEBUG("Mapping %s at %p through %d", loc, mem, fd);
+    XBT_DEBUG("Shared malloc %zu in %p (metadata at %p)", size, mem, data);
   } else {
-    mem = shm_map(data->fd, size, data);
-    data->count++;
+    mem = xbt_malloc(size);
+    XBT_DEBUG("Classic malloc %zu in %p", size, mem);
   }
-  XBT_DEBUG("Malloc %zu in %p (metadata at %p)", size, mem, data);
+
   return mem;
 }
 void smpi_shared_free(void *ptr)
@@ -393,33 +454,39 @@ void smpi_shared_free(void *ptr)
   char loc[PTR_STRLEN];
   shared_metadata_t* meta;
   shared_data_t* data;
-
-  if (!allocs) {
-    XBT_WARN("Cannot free: nothing was allocated");
-    return;
-  }
-  if(!allocs_metadata) {
-    XBT_WARN("Cannot free: no metadata was allocated");
-  }
-  snprintf(loc, PTR_STRLEN, "%p", ptr);
-  meta = (shared_metadata_t*)xbt_dict_get_or_null(allocs_metadata, loc);
-  if (!meta) {
-    XBT_WARN("Cannot free: %p was not shared-allocated by SMPI", ptr);
-    return;
-  }
-  data = meta->data;
-  if(!data) {
-    XBT_WARN("Cannot free: something is broken in the metadata link");
-    return;
-  }
-  if(munmap(ptr, meta->size) < 0) {
-    XBT_WARN("Unmapping of fd %d failed: %s", data->fd, strerror(errno));
-  }
-  data->count--;
-  if (data->count <= 0) {
-    close(data->fd);
-    xbt_dict_remove(allocs, data->loc);
-    free(data->loc);
+  if (sg_cfg_get_boolean("smpi/use_shared_malloc")){
+  
+    if (!allocs) {
+      XBT_WARN("Cannot free: nothing was allocated");
+      return;
+    }
+    if(!allocs_metadata) {
+      XBT_WARN("Cannot free: no metadata was allocated");
+    }
+    snprintf(loc, PTR_STRLEN, "%p", ptr);
+    meta = (shared_metadata_t*)xbt_dict_get_or_null(allocs_metadata, loc);
+    if (!meta) {
+      XBT_WARN("Cannot free: %p was not shared-allocated by SMPI", ptr);
+      return;
+    }
+    data = meta->data;
+    if(!data) {
+      XBT_WARN("Cannot free: something is broken in the metadata link");
+      return;
+    }
+    if(munmap(ptr, meta->size) < 0) {
+      XBT_WARN("Unmapping of fd %d failed: %s", data->fd, strerror(errno));
+    }
+    data->count--;
+    XBT_DEBUG("Shared free - no removal - of %p, count = %d", ptr, data->count);
+    if (data->count <= 0) {
+      close(data->fd);
+      xbt_dict_remove(allocs, data->loc);
+      XBT_DEBUG("Shared free - with removal - of %p", ptr);
+    }
+  }else{
+    XBT_DEBUG("Classic free of %p", ptr);
+    xbt_free(ptr);
   }
 }
 #endif