Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Adding code for benchmarking code block v3_9_90
authorLuka Stanisic <luka.stanisic@imag.fr>
Tue, 22 Oct 2013 08:33:02 +0000 (10:33 +0200)
committerLuka Stanisic <luka.stanisic@imag.fr>
Tue, 22 Oct 2013 08:33:02 +0000 (10:33 +0200)
contrib/benchmarking_code_block/Rhist.R [new file with mode: 0644]
contrib/benchmarking_code_block/bench.h [new file with mode: 0644]
contrib/benchmarking_code_block/inject.h [new file with mode: 0644]

diff --git a/contrib/benchmarking_code_block/Rhist.R b/contrib/benchmarking_code_block/Rhist.R
new file mode 100644 (file)
index 0000000..92fe61b
--- /dev/null
@@ -0,0 +1,37 @@
+# R script that produces histograms from benchmarked values
+
+# Can be called from the bash script with the following code:
+# export R_INPUT=$inputfile
+# export R_OUTPUT=$outputfile
+# R CMD BATCH $this_script.R
+
+# Use functions from bench.h to benchmark execution time of the desired block,
+# then Rhist.R script to read all timings and produce histograms
+# and finally inject.h to inject values instead of executing block
+
+  
+inputfile<-Sys.getenv("R_INPUT")
+outputfile<-Sys.getenv("R_OUTPUT")
+
+df<-read.table(inputfile,header=F)
+df<-df[,c(1,4)]
+names(df)<-c("NAME","TIME")
+attach(df)
+
+for(i in unique(NAME))
+{
+  vector1<-df[NAME==i,2]
+  h<-hist(vector1)
+  
+  cat(i, file = outputfile, sep = "\t", append = TRUE)
+  cat("  ", file = outputfile, sep = "\t", append = TRUE)
+  cat(sprintf("%.8f", mean(vector1)), file =outputfile, sep = "\t ", append = TRUE)
+  cat("\t", file = outputfile,  append = TRUE)
+  cat(length(h$breaks), file = outputfile, append = TRUE)
+  cat("\t", file = outputfile,  append = TRUE)
+  cat(sprintf("%.8f", h$breaks), file = outputfile, sep = " \t", append = TRUE)
+  cat("\t", file = outputfile,  append = TRUE)
+  h$density = h$counts/sum(h$counts)
+  cat(sprintf("%.14f", h$density), file = outputfile, sep = " \t", append = TRUE)
+  cat("\n", file = outputfile,  append = TRUE)
+}
diff --git a/contrib/benchmarking_code_block/bench.h b/contrib/benchmarking_code_block/bench.h
new file mode 100644 (file)
index 0000000..fc86bc3
--- /dev/null
@@ -0,0 +1,162 @@
+/* Copy to src/include/xbt/ folder  */
+
+/* Benchmarking a code block */
+
+/* Use functions from bench.h to benchmark execution time of the desired block,
+ * then Rhist.R script to read all timings and produce histograms
+ * and finally inject.h to inject values instead of executing block*/
+
+#ifndef __BENCH_H__
+#define __BENCH_H__
+
+#include <time.h>
+#include <stdio.h>
+#include <string.h>
+
+/* Structure that has all benchmarking information for the block*/
+typedef struct bench {
+       struct timespec start_time;
+       struct timespec end_time;
+       int benchmarking;
+       char block_id[256];
+       char suffix[100];
+       FILE* output;
+}*bench_t;
+
+extern bench_t get_mybench(void);
+typedef bench_t (*get_bench_func_t)(void);
+
+/* In order to divide nanoseconds and get result in seconds */
+#define BILLION  1000000000L
+
+/* Macros for benchmarking */
+#define BENCH_BLOCK(block_id) for(bench_begin_block();bench_end_block(block_id);)
+#define BENCH_EXTEND(block_id) xbt_bench_extend(block_id)
+
+static inline void xbt_bench_init(char *tracefile);
+static inline void bench_init_starpu(char *tracefile, bench_t *bench);
+
+static inline void bench_begin_block();
+static inline int bench_end_block(char* block_id);
+
+static inline void xbt_bench_begin(char* block_id);
+static inline int xbt_bench_end(char* block_id);
+
+static inline void xbt_bench_extend(char* block_id);
+
+/* Additional functions in order to manipulate with struct timespec */
+static inline void xbt_diff_time(struct timespec* start, struct timespec* end, struct timespec* result_time);
+static inline double xbt_get_time(struct timespec* timer);
+
+/* Initializing SMPI benchmarking */
+static inline void xbt_bench_init(char *tracefile)
+{
+       bench_t mybench = get_mybench();
+       mybench->output = fopen(tracefile, "a+");
+       if (mybench->output == NULL)
+               printf("Error while opening the tracefile");
+
+}
+
+/* Initializing StarPU benchmarking */
+static inline void bench_init_starpu(char *tracefile, bench_t *bench)
+{
+  *bench = (bench_t) malloc(sizeof(**bench));
+  bench_t mybench = *bench;
+  mybench->output = fopen(tracefile, "a+");
+  if (mybench->output == NULL)
+               printf("Error while opening the tracefile");
+
+}
+
+/* Start benchmarking using macros */
+static inline void bench_begin_block()
+{
+       bench_t mybench = get_mybench();
+       clock_gettime(CLOCK_REALTIME, &mybench->start_time);
+       mybench->benchmarking = 1; // Only benchmarking once
+}
+
+/* End benchmarking using macros */
+static inline int bench_end_block(char* block_id)
+{
+       bench_t mybench = get_mybench();
+       if (mybench->benchmarking > 0)
+       {
+               mybench->benchmarking--;
+               return 1;
+       }
+       else
+       {
+               clock_gettime(CLOCK_REALTIME, &mybench->end_time);
+               struct timespec interval;
+               xbt_diff_time(&mybench->start_time, &mybench->end_time, &interval);
+               fprintf(mybench->output, "%s %lf %lf %lf\n", block_id, xbt_get_time(&mybench->start_time), xbt_get_time(&mybench->end_time), xbt_get_time(&interval));
+               return 0;
+       }
+}
+
+/* Start SMPI benchmarking */
+static inline void xbt_bench_begin(char* block_id)
+{
+       bench_t mybench = get_mybench();
+       if(block_id != NULL)
+               strcpy (mybench->block_id, block_id);
+       else
+               strcpy (mybench->block_id, "");
+       clock_gettime(CLOCK_REALTIME, &mybench->start_time);
+       mybench->benchmarking = 1; // Only benchmarking once
+}
+
+/* End SMPI benchmarking */
+static inline int xbt_bench_end(char* block_id)
+{
+       bench_t mybench = get_mybench();
+
+       clock_gettime(CLOCK_REALTIME, &mybench->end_time);
+       struct timespec interval;
+       xbt_diff_time(&mybench->start_time, &mybench->end_time, &interval);
+
+       if(mybench->suffix != NULL)
+       {
+               strcat (mybench->block_id, mybench->suffix);
+               strcpy (mybench->suffix, "");
+       }
+       if(block_id != NULL)
+               strcat (mybench->block_id, block_id);
+       if(mybench->block_id == NULL)
+               strcat (mybench->block_id, "NONAME");
+
+       fprintf(mybench->output, "%s %lf %lf %lf\n", mybench->block_id, xbt_get_time(&mybench->start_time), xbt_get_time(&mybench->end_time), xbt_get_time(&interval));
+       return 0;
+}
+
+/* Extending the block_id name*/
+static inline void xbt_bench_extend(char* block_id)
+{
+       bench_t mybench = get_mybench();
+       strcpy (mybench->suffix, block_id);
+}
+
+/* Calculating time difference */
+static inline void xbt_diff_time(struct timespec* start, struct timespec* end, struct timespec* result_time)
+{
+       if ((end->tv_nsec - start->tv_nsec) < 0)
+       {
+               result_time->tv_sec = end->tv_sec - start->tv_sec - 1;
+               result_time->tv_nsec = (double) BILLION + end->tv_nsec - start->tv_nsec;
+       }
+       else
+       {
+               result_time->tv_sec = end->tv_sec - start->tv_sec;
+               result_time->tv_nsec = end->tv_nsec - start->tv_nsec;
+       }
+}
+
+/* Printing time in "double" format */
+static inline double xbt_get_time(struct timespec* timer)
+{
+       return timer->tv_sec + (double) (timer->tv_nsec / (double) BILLION);
+}
+
+#endif //__BENCH_H__
diff --git a/contrib/benchmarking_code_block/inject.h b/contrib/benchmarking_code_block/inject.h
new file mode 100644 (file)
index 0000000..ba23a65
--- /dev/null
@@ -0,0 +1,198 @@
+/* Copy to src/include/xbt/ folder  */
+
+/* Injecting timings for previously benchmarked code blocks */
+
+/* Use functions from bench.h to benchmark execution time of the desired block,
+ * then Rhist.R script to read all timings and produce histograms
+ * and finally inject.h to inject values instead of executing block*/
+
+#ifndef __INJECT_H__
+#define __INJECT_H__
+
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "xbt/RngStream.h"
+#include "xbt/dict.h"
+#include "xbt/sysdep.h"
+
+#define MAX_LINE_INJ 1000
+
+/*
+ * Histogram entry for each measured block
+ * Each entry is guarded inside xbt dictionary which is read from the file */
+typedef struct xbt_hist {
+       int n;
+       double mean;
+       double *breaks;
+       double *percentage;
+       char* block_id;
+} xbt_hist_t;
+
+extern RngStream get_randgen(void);
+typedef RngStream (*get_randgen_func_t)(void);
+
+extern xbt_dict_t get_dict(void);
+typedef xbt_dict_t (*get_dict_func_t)(void);
+
+static inline void xbt_inject_init(char *inputfile);
+static inline void inject_init_starpu(char *inputfile, xbt_dict_t *dict, RngStream *rng);
+
+static inline double xbt_inject_time(char *key);
+static inline double xbt_mean_time(char *key);
+static inline double xbt_hist_time(char *key);
+
+/* Initializing xbt dictionary for SMPI version, reading xbt_hist_t entries line by line */
+static inline void xbt_inject_init(char *inputfile)
+{
+       xbt_dict_t mydict = get_dict();
+       FILE* fpInput = fopen(inputfile, "r");
+       if (fpInput == NULL)
+               printf("Error while opening the inputfile");
+       fseek(fpInput, 0, 0);
+
+       char line[200];
+       char *key;
+       int i;
+       xbt_hist_t* data;
+
+       if (fgets(line, 200, fpInput) == NULL)
+               printf("Error input file is empty!");//Skipping first row
+       while (fgets(line, 200, fpInput) != NULL)
+       {
+               key = strtok(line, " \t");
+
+               data = xbt_dict_get_or_null(mydict, key);
+               if (data)
+                       printf("Error, data with that block_id already exists!");
+
+               data = (xbt_hist_t *) xbt_new(xbt_hist_t, 1);
+
+               data->block_id = key;
+               data->mean = atof(strtok(NULL, " \t"));
+               data->n = atoi(strtok(NULL, " \t"));
+
+               data->breaks = (double*) malloc(sizeof(double) * data->n);
+               data->percentage = (double*) malloc(sizeof(double) * (data->n - 1));
+               for (i = 0; i < data->n; i++)
+                       data->breaks[i] = atof(strtok(NULL, " \t"));
+               for (i = 0; i < (data->n - 1); i++)
+                       data->percentage[i] = atof(strtok(NULL, " \t"));
+
+               xbt_dict_set(mydict, key, data, NULL);
+       }
+}
+
+/* Initializing xbt dictionary for StarPU version, reading xbt_hist_t entries line by line */
+static inline void inject_init_starpu(char *inputfile, xbt_dict_t *dict, RngStream *rng)
+{
+       *dict = xbt_dict_new_homogeneous(free);
+       *rng = RngStream_CreateStream("Randgen1");
+       unsigned long seed[] = {134, 233445, 865, 2634, 424242, 876541};
+       RngStream_SetSeed(*rng, seed);
+
+       xbt_dict_t mydict = *dict;
+       mydict = *dict;
+       FILE* fpInput = fopen(inputfile, "r");
+       if (fpInput == NULL)
+               printf("Error while opening the inputfile");
+
+       fseek(fpInput, 0, 0);
+
+       char line[MAX_LINE_INJ];
+       char *key;
+       int i;
+       xbt_hist_t* data;
+
+       if (fgets(line, MAX_LINE_INJ, fpInput) == NULL)
+               printf("Error input file is empty!");//Skipping first row
+
+
+       while (fgets(line, MAX_LINE_INJ, fpInput) != NULL)
+       {
+               key = strtok(line, " \t");
+
+               data = xbt_dict_get_or_null(mydict, key);
+               if (data)
+                       printf("Error, data with that block_id already exists!");
+
+               data = (xbt_hist_t *) xbt_new(xbt_hist_t, 1);
+               data->block_id = key;
+               data->mean = atof(strtok(NULL, " \t"));
+               data->n = atoi(strtok(NULL, " \t"));
+               data->breaks = (double*) malloc(sizeof(double) * data->n);
+               data->percentage = (double*) malloc(sizeof(double) * (data->n - 1));
+
+               for (i = 0; i < data->n; i++)
+                       data->breaks[i] = atof(strtok(NULL, " \t"));
+                       for (i = 0; i < (data->n - 1); i++)
+                       {
+                               data->percentage[i] = atof(strtok(NULL, " \t"));
+                       }
+
+               xbt_dict_set(mydict, key, data, NULL);
+       }
+}
+
+/* Injecting time */
+static inline double xbt_inject_time(char *key)
+{
+       return xbt_hist_time(key);
+       //return xbt_mean_time(key);
+}
+
+/* Injecting mean value */
+static inline double xbt_mean_time(char *key)
+{
+       xbt_dict_t mydict = get_dict();
+       xbt_hist_t* data = xbt_dict_get_or_null(mydict, key);
+
+       if (!data)
+       {
+         printf("Warning: element with specified key does not exist (%s)\n",key);
+         return 0;
+       }
+
+       return data->mean;
+}
+
+/* Injecting random value from the histogram */
+static inline double xbt_hist_time(char *key)
+{
+       int i, k = 0;
+       double left = 0, right = 1;
+       double timer = 0;
+       RngStream rng_stream;
+       double r, r2;
+
+       xbt_dict_t mydict = get_dict();
+       xbt_hist_t* data = xbt_dict_get_or_null(mydict, key);
+
+       if (!data)
+               {
+                 printf("Warning: element with specified key does not exist (%s)\n",key);
+                 return 0;
+               }
+
+       /* Choosing random interval of the histogram */
+       rng_stream = get_randgen();
+       r = RngStream_RandU01(rng_stream);
+       for (i = 0; i < (data->n - 1); i++)
+       {
+               left += (i == 0) ? 0 : data->percentage[i - 1];
+               right += data->percentage[i];
+               if (left < r && r <= right)
+                       k = i;
+       }
+
+       /* Choosing random value inside the interval of the histogram */
+       r2 = RngStream_RandU01(rng_stream);
+       timer = data->breaks[k] + r2 * (data->breaks[k + 1] - data->breaks[k]);
+
+       return timer;
+}
+
+#endif // __INJECT_H__
+