From 045db1657e870c721be490b411868f4181a12ced Mon Sep 17 00:00:00 2001 From: Luka Stanisic Date: Tue, 22 Oct 2013 10:33:02 +0200 Subject: [PATCH] Adding code for benchmarking code block --- contrib/benchmarking_code_block/Rhist.R | 37 +++++ contrib/benchmarking_code_block/bench.h | 162 +++++++++++++++++++ contrib/benchmarking_code_block/inject.h | 198 +++++++++++++++++++++++ 3 files changed, 397 insertions(+) create mode 100644 contrib/benchmarking_code_block/Rhist.R create mode 100644 contrib/benchmarking_code_block/bench.h create mode 100644 contrib/benchmarking_code_block/inject.h diff --git a/contrib/benchmarking_code_block/Rhist.R b/contrib/benchmarking_code_block/Rhist.R new file mode 100644 index 0000000000..92fe61be7e --- /dev/null +++ b/contrib/benchmarking_code_block/Rhist.R @@ -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 index 0000000000..fc86bc3db0 --- /dev/null +++ b/contrib/benchmarking_code_block/bench.h @@ -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 +#include +#include + +/* 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 index 0000000000..ba23a6508e --- /dev/null +++ b/contrib/benchmarking_code_block/inject.h @@ -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 +#include +#include +#include +#include +#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__ + -- 2.20.1