#ifndef BENCHMARK_H_ #define BENCHMARK_H_ #include #include #include #ifdef ENABLE_PAPI #include #endif #include "rib.h" #include "config.h" #include "params.h" class ThrashingBenchmark; enum BenchmarkState { STATE_UNSET, STATE_WARMUP, STATE_MEASURE_TIME, STATE_MEASURE_PAPI, }; class Benchmark { public: virtual ~Benchmark(); /* * Initialize the parameters of the benchmarks from the ini file. * Also deletes unused parameters and empties the iniParams. */ virtual void initialize_params (std::map & iniParams, bool plot, bool papi); std::string table_filename(int depth); virtual bool nextRun(); std::string result_filename(); // virtual std::string benchmark_name() = 0; virtual void benchmark(size_t warmupCount, size_t samplesCount, ThrashingBenchmark * thrasher, tsc_t * results) = 0; virtual int result_cols_num() = 0; virtual int result_rows_num() = 0; // resultHeader: column name including T_ but with ':' converted to '.' // second: PAPI event name with ':' struct column_name { std::string resultHeader; std::string papiEvent; std::string ylab; column_name (std::string _resultHeader, std::string _papiEvent, std::string _ylab) : resultHeader (_resultHeader), papiEvent (_papiEvent), ylab (_ylab) {}; }; virtual std::list< column_name > get_result_columns() = 0; virtual void print_result_cols_header(std::ostream &s, std::string prefix); static Benchmark * CreateBenchmark(std::string btype); unsigned papi_sets_count(); const std::string benchmark_name; // parameter manager of the benchmark BenchParams params; virtual bool advance_params(int skip_depth1, int skip_depth2 = -1); // in what state the benchmark currently runs BenchmarkState state; #ifdef ENABLE_PAPI void papi_start_counting(unsigned set); void papi_stop_counting(unsigned set); #endif /* ENABLE_PAPI */ protected: Benchmark(std::string benchmark_name); Benchmark(); std::vector & get_param_defs(); // inline helpers for frequently used params access inline void def_param(std::string name, param_type type) { params.allDefs.push_back(param_def(name, type)); } inline void def_param(std::string name, param_type type, param_mult mult) { params.allDefs.push_back(param_def(name, type, mult)); } inline void def_param_unmanaged(std::string name, param_type type) { params.allDefs.push_back(param_def(name, type, false)); } inline size_t get_numeric_param_current (const std::string & param_name) { return params.currentNumeric(param_name); } inline std::string get_string_param_current (const std::string & param_name) { return params.currentString(param_name); } std::string result_filename(std::string prefix); unsigned papi_sets_cnt; // initialize parameters virtual void init() = 0; #ifdef ENABLE_PAPI void papi_start(unsigned set); void papi_stop(unsigned set, tsc_t * res, tsc_t clocks); std::list get_papi_result_names(); int get_papi_result_count(); int papi_counters; int * papi_sets; std::vector papi_event_names; int * papi_event_codes; int papi_events_cnt; unsigned * papi_events_order; long long * papi_values_start; long long * papi_values; virtual void papi_init(int _papi_counters); #endif }; class ThrashingBenchmark : virtual public Benchmark { public: virtual void prepareThrash() = 0; virtual void thrash(tsc_t * results, int papi_set) = 0; static ThrashingBenchmark * CreateThrashingBenchmark(std::string btype); }; class DummyThrasher : public ThrashingBenchmark { private: bool will_run; public: DummyThrasher() : Benchmark("none") { will_run = false; }; int param_count_all() { return 0; }; const param_def * get_param_defs() { return NULL; }; bool advance_params(int /* skip_depth1 */, int /* skip_depth2 */ = -1) { params.setCurrentOrder(-1); will_run = !will_run; return will_run; }; bool nextRun() { return advance_params(-1); }; void benchmark(size_t /* warmupCount */, size_t /* samplesCount */, ThrashingBenchmark * /* thrasher */, tsc_t * /* results */) {}; int result_cols_num() { return 0; }; int result_rows_num() { return 0; }; std::list get_result_columns() { return std::list(); }; void prepareThrash() {}; void thrash(tsc_t * /* results */, int /* papi_set */) {}; void init() {}; }; class BenchFactory { public: virtual Benchmark * newBenchmark() = 0; virtual ThrashingBenchmark * newThrashingBenchmark() = 0; virtual ~BenchFactory() {}; }; class FactoriesMapHolder { private: std::map benchFactoryMap; std::map benchThrashingFactoryMap; public: std::map & getBenchFactoryMap() { return benchFactoryMap; } std::map & getThrashingBenchFactoryMap() { return benchThrashingFactoryMap; } static FactoriesMapHolder & getInstance(); ~FactoriesMapHolder(); }; #define BENCHFACTORY(benchName,benchClass) \ class BenchFactoryImpl##benchClass : BenchFactory { \ public: \ BenchFactoryImpl##benchClass() { \ FactoriesMapHolder::getInstance().getBenchFactoryMap()[benchName] = this; \ } \ \ virtual Benchmark * newBenchmark() { \ return new benchClass(); \ } \ \ virtual ThrashingBenchmark * newThrashingBenchmark() { \ return NULL; \ } \ }; \ static BenchFactoryImpl##benchClass * factory##benchClass = new BenchFactoryImpl##benchClass(); #define THRASHINGBENCHFACTORY(benchName,benchClass) \ class BenchFactoryImpl##benchClass : BenchFactory { \ public: \ BenchFactoryImpl##benchClass() { \ FactoriesMapHolder::getInstance().getBenchFactoryMap()[benchName] = this; \ FactoriesMapHolder::getInstance().getThrashingBenchFactoryMap()[benchName] = this; \ } \ \ virtual Benchmark * newBenchmark() { \ return new benchClass(); \ } \ \ virtual ThrashingBenchmark * newThrashingBenchmark() { \ return new benchClass(); \ } \ }; \ static BenchFactoryImpl##benchClass * factory##benchClass = new BenchFactoryImpl##benchClass(); #endif /*BENCHMARK_H_*/