diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index fc14791..6397c1a 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -69,6 +69,18 @@ jobs: run: | brew install zmq + # PACKAGE MANAGER PAPI INSTALL + - name: Install papi (linux) + if: runner.os == 'linux' + run: | + sudo apt-get install libpapi-dev papi-tools + + # PACKAGE MANAGER PERF INSTALL + - name: Install perf (linux) + if: runner.os == 'linux' + run: | + sudo apt-get install linux-tools-generic + - uses: r-lib/actions/setup-r-dependencies@v2 with: extra-packages: any::rcmdcheck diff --git a/R/RcppExports.R b/R/RcppExports.R index f7d88db..74a9f22 100644 --- a/R/RcppExports.R +++ b/R/RcppExports.R @@ -5,10 +5,11 @@ #' @param max_nprocs Maximum number of R processes (ie evtWriters required) #' @param archivePath Path to otf2 archive #' @param archiveName Name of otf2 archive +#' @param collect_metrics Collect HWPC metrics via pmpmeas #' @param flag_print_pids True to print pids of parent and child procs #' @return <0 if error, 0 if R master, else >0 if child -init_otf2_logger <- function(max_nprocs, archivePath = "./rTrace", archiveName = "rTrace", flag_print_pids = FALSE) { - .Call('_rTrace_init_otf2_logger', PACKAGE = 'rTrace', max_nprocs, archivePath, archiveName, flag_print_pids) +init_otf2_logger <- function(max_nprocs, archivePath = "./rTrace", archiveName = "rTrace", collect_metrics = FALSE, flag_print_pids = FALSE) { + .Call('_rTrace_init_otf2_logger', PACKAGE = 'rTrace', max_nprocs, archivePath, archiveName, collect_metrics, flag_print_pids) } #' assign_regionRef_array_master diff --git a/R/rTrace.R b/R/rTrace.R index ccd6a9a..1302ba7 100644 --- a/R/rTrace.R +++ b/R/rTrace.R @@ -96,12 +96,12 @@ pkg.env$PRINT_FUNC_INDEXES <- FALSE pkg.env$COLLECT_METRICS <- FALSE -# @name RTRACE_VARS -# @description List of all global rTrace variables -pkg.env$RTRACE_VARS <- c( "INSTRUMENTATION_INIT", "INSTRUMENTATION_ENABLED", - "INSTRUMENTATION_STATUS_SAVED", "MAX_FUNCTION_DEPTH", - "FUNCTION_DEPTH", "UNLOCK_ENVS", "PRINT_INSTRUMENTS", - "PRINT_SKIPS", "PRINT_FUNC_INDEXES", - "COLLECT_METRICS" - ) +## @name RTRACE_VARS +## @description List of all global rTrace variables +#pkg.env$RTRACE_VARS <- c( "INSTRUMENTATION_INIT", "INSTRUMENTATION_ENABLED", +# "INSTRUMENTATION_STATUS_SAVED", "MAX_FUNCTION_DEPTH", +# "FUNCTION_DEPTH", "UNLOCK_ENVS", "PRINT_INSTRUMENTS", +# "PRINT_SKIPS", "PRINT_FUNC_INDEXES", +# "COLLECT_METRICS" +# ) diff --git a/R/r_exception_list.R b/R/r_exception_list.R index 0bc58a9..472abf9 100644 --- a/R/r_exception_list.R +++ b/R/r_exception_list.R @@ -63,7 +63,8 @@ get_function_exception_list <- function() { # These functions contain on.exit() and blocks instrumentation insert on.exit_functions <- c() - if (R.utils::isPackageLoaded("R.utils")){ on.exit_functions <- append(on.exit_functions, c(R.utils::read.table)) } + #if (R.utils::isPackageLoaded("R.utils")){ on.exit_functions <- append(on.exit_functions, c(R.utils::read.table)) } + if (R.utils::isPackageLoaded("utils")){ on.exit_functions <- append(on.exit_functions, c(utils::read.table)) } function_exception_list <- append(function_exception_list, on.exit_functions) diff --git a/R/r_fork_functions.R b/R/r_fork_functions.R index 214549d..52738d3 100644 --- a/R/r_fork_functions.R +++ b/R/r_fork_functions.R @@ -396,6 +396,14 @@ master_init_slave <- function(cl) { parallel::clusterExport(cl, c("pkg_cmd"), envir=environment()) parallel::clusterEvalQ(cl, eval(parse(text = pkg_cmd))) + ## Attempted to store as pkg.env$RTRACE_VARS in rTrace.R, results in error + RTRACE_VARS <- c( "INSTRUMENTATION_INIT", "INSTRUMENTATION_ENABLED", + "INSTRUMENTATION_STATUS_SAVED", "MAX_FUNCTION_DEPTH", + "FUNCTION_DEPTH", "UNLOCK_ENVS", "PRINT_INSTRUMENTS", + "PRINT_SKIPS", "PRINT_FUNC_INDEXES", + "COLLECT_METRICS" + ) + # Export rTrace variables parallel::clusterExport(cl, c("RTRACE_VARS"), envir=environment()) parallel::clusterExport(cl, RTRACE_VARS, envir=pkg.env) diff --git a/R/r_instrument_hl.R b/R/r_instrument_hl.R index 283ab55..8061067 100644 --- a/R/r_instrument_hl.R +++ b/R/r_instrument_hl.R @@ -72,11 +72,10 @@ instrumentation_init <- function(flag_user_functions=T, collect_metrics=F, verbo ## Interface to pmpmeas if (collect_metrics){ pkg.env$COLLECT_METRICS <- TRUE - pmpmeas_init() } ## Initiate new proc - close R if not Master - ret <- init_otf2_logger(parallelly::availableCores()) # Master R proc returns 0 + ret <- init_otf2_logger(parallelly::availableCores(), collect_metrics=collect_metrics) # Master R proc returns 0 if (ret != 0){ quit(save="no"); } # Unintended fork R proc for otf2 logger ## Assign array on logger proc for regionRef of each func diff --git a/man/init_otf2_logger.Rd b/man/init_otf2_logger.Rd index 30c7785..c69031f 100644 --- a/man/init_otf2_logger.Rd +++ b/man/init_otf2_logger.Rd @@ -8,6 +8,7 @@ init_otf2_logger( max_nprocs, archivePath = "./rTrace", archiveName = "rTrace", + collect_metrics = FALSE, flag_print_pids = FALSE ) } @@ -18,6 +19,8 @@ init_otf2_logger( \item{archiveName}{Name of otf2 archive} +\item{collect_metrics}{Collect HWPC metrics via pmpmeas} + \item{flag_print_pids}{True to print pids of parent and child procs} } \value{ diff --git a/man/instrumentation_init.Rd b/man/instrumentation_init.Rd index a689df0..5dd7097 100644 --- a/man/instrumentation_init.Rd +++ b/man/instrumentation_init.Rd @@ -4,12 +4,18 @@ \alias{instrumentation_init} \title{instrumentation_init} \usage{ -instrumentation_init(flag_user_functions = T, verbose_wrapping = F) +instrumentation_init( + flag_user_functions = T, + collect_metrics = F, + verbose_wrapping = F +) } \arguments{ \item{flag_user_functions}{Boolean - TRUE to include user functions in dataframe} -\item{verbose_wrapping}{Boolean - Print info about skipping or instrumenting each function. Produces large amount of info to stdout} +\item{collect_metrics}{Boolean - Enable papi/perf metric collection with instrumentation} + +\item{verbose_wrapping}{Boolean - Print info about skipping or instrumenting each function. Produces large amount of info to stdout. Intended for developers} } \description{ Create otf2 objs for instrumentation, and initiate global vars diff --git a/man/pkg.env.Rd b/man/pkg.env.Rd index 82b331e..90a71ef 100644 --- a/man/pkg.env.Rd +++ b/man/pkg.env.Rd @@ -17,6 +17,8 @@ \item{PRINT_INSTRUMENTS}{} \item{PRINT_SKIPS}{} \item{PRINT_FUNC_INDEXES}{} +\item{COLLECT_METRICS}{} +\item{RTRACE_VARS}{} } } \usage{ diff --git a/src/Makevars b/src/Makevars index 79cfb95..06f9b6d 100644 --- a/src/Makevars +++ b/src/Makevars @@ -7,8 +7,17 @@ ZEROMQ_PKG_CPPFLAGS=-I${ZEROMQ_ROOT}/include ZEROMQ_PKG_LIBS=-L${ZEROMQ_ROOT}/lib -lzmq # pmpmeas - papi -PMPMEAS_PKG_CPPFLAGS=`pkg-config --cflags papi` -PMPMEAS_PKG_LIBS=`pkg-config --libs papi` +# num = PAPI_get_opt(PAPI_MAX_HWCTRS,NULL) +# papi_avail | grep "Number Hardware Counters :" | sed -e "s|Number Hardware Counters : ||g" +#PAPICNTMAX=3 +#PAPICNTMAX=`papi_avail | grep "Number Hardware Counters :" | sed -e "s|Number Hardware Counters : ||"` +#PMPMEAS_PKG_CPPFLAGS=`pkg-config --cflags papi` -DUSEPAPI -DPAPICNTMAX=${PAPICNTMAX} -DRTRACE_SUPPORT -D_COLLECT_METRICS +#PMPMEAS_PKG_LIBS=`pkg-config --libs papi` +# +PAPICNTMAX=$(papi_avail | grep "Number Hardware Counters :" | sed -e "s|Number Hardware Counters : ||") +PMPMEAS_PKG_CPPFLAGS=$(pkg-config --cflags papi) -DUSEPAPI -DPAPICNTMAX=${PAPICNTMAX} -DRTRACE_SUPPORT -D_COLLECT_METRICS +PMPMEAS_PKG_LIBS=$(pkg-config --libs papi) PKG_CPPFLAGS=-I. ${OTF2_PKG_CPPFLAGS} ${ZEROMQ_PKG_CPPFLAGS} ${PMPMEAS_PKG_CPPFLAGS} -PKG_LIBS=-L. ${OTF2_PKG_LIBS} ${ZEROMQ_PKG_LIBS} ${PMPMMEAS_PKG_LIBS} +PKG_LIBS=-L. ${OTF2_PKG_LIBS} ${ZEROMQ_PKG_LIBS} ${PMPMEAS_PKG_LIBS} + diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp index 8a3d893..a38ccb6 100644 --- a/src/RcppExports.cpp +++ b/src/RcppExports.cpp @@ -11,16 +11,17 @@ Rcpp::Rostream& Rcpp::Rcerr = Rcpp::Rcpp_cerr_get(); #endif // init_otf2_logger -RcppExport int init_otf2_logger(int max_nprocs, Rcpp::String archivePath, Rcpp::String archiveName, bool flag_print_pids); -RcppExport SEXP _rTrace_init_otf2_logger(SEXP max_nprocsSEXP, SEXP archivePathSEXP, SEXP archiveNameSEXP, SEXP flag_print_pidsSEXP) { +RcppExport int init_otf2_logger(int max_nprocs, Rcpp::String archivePath, Rcpp::String archiveName, bool collect_metrics, bool flag_print_pids); +RcppExport SEXP _rTrace_init_otf2_logger(SEXP max_nprocsSEXP, SEXP archivePathSEXP, SEXP archiveNameSEXP, SEXP collect_metricsSEXP, SEXP flag_print_pidsSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< int >::type max_nprocs(max_nprocsSEXP); Rcpp::traits::input_parameter< Rcpp::String >::type archivePath(archivePathSEXP); Rcpp::traits::input_parameter< Rcpp::String >::type archiveName(archiveNameSEXP); + Rcpp::traits::input_parameter< bool >::type collect_metrics(collect_metricsSEXP); Rcpp::traits::input_parameter< bool >::type flag_print_pids(flag_print_pidsSEXP); - rcpp_result_gen = Rcpp::wrap(init_otf2_logger(max_nprocs, archivePath, archiveName, flag_print_pids)); + rcpp_result_gen = Rcpp::wrap(init_otf2_logger(max_nprocs, archivePath, archiveName, collect_metrics, flag_print_pids)); return rcpp_result_gen; END_RCPP } @@ -258,7 +259,7 @@ END_RCPP } static const R_CallMethodDef CallEntries[] = { - {"_rTrace_init_otf2_logger", (DL_FUNC) &_rTrace_init_otf2_logger, 4}, + {"_rTrace_init_otf2_logger", (DL_FUNC) &_rTrace_init_otf2_logger, 5}, {"_rTrace_assign_regionRef_array_master", (DL_FUNC) &_rTrace_assign_regionRef_array_master, 1}, {"_rTrace_assign_regionRef_array_slave", (DL_FUNC) &_rTrace_assign_regionRef_array_slave, 1}, {"_rTrace_get_regionRef_from_array_slave", (DL_FUNC) &_rTrace_get_regionRef_from_array_slave, 1}, diff --git a/src/m_pmpmeas.f90 b/src/m_pmpmeas.f90 new file mode 100644 index 0000000..f86d9a7 --- /dev/null +++ b/src/m_pmpmeas.f90 @@ -0,0 +1,59 @@ +! ------- +! PMPMEAS +! ------- +! +! Copyright 2022 Dirk Pleiter (pleiter@kth.se) +! +! Redistribution and use in source and binary forms, with or without +! modification, are permitted provided that the following conditions +! are met: +! +! 1. Redistributions of source code must retain the above copyright +! notice, this list of conditions and the following disclaimer. +! +! 2. The origin of this software must not be misrepresented; you must +! not claim that you wrote the original software. If you use this +! software in a product, an acknowledgment in the product +! documentation would be appreciated but is not required. +! +! 3. Altered source versions must be plainly marked as such, and must +! not be misrepresented as being the original software. +! +! 4. The name of the author may not be used to endorse or promote +! products derived from this software without specific prior written +! permission. +! +! THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +! OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +! WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +! ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +! DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +! DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +! GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +! WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +! NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +! SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +module M_PMPMEAS + use ISO_C_BINDING, only : C_CHAR, C_FLOAT + interface + + subroutine pmpmeas_init() bind(C,name='pmpmeas_init') + end subroutine + + subroutine pmpmeas_start(tag) bind(C,name='pmpmeas_start') + import C_CHAR + character(kind=C_CHAR),dimension(*) :: tag + end subroutine + + subroutine pmpmeas_stop(weight) bind(C,name='pmpmeas_stop_fortran') + import C_FLOAT + real(kind=C_FLOAT) :: weight + end subroutine + + subroutine pmpmeas_finish() bind(C,name='pmpmeas_finish') + end subroutine + + end interface +end module diff --git a/src/m_pmpmeas.mod b/src/m_pmpmeas.mod new file mode 100644 index 0000000..2555cab Binary files /dev/null and b/src/m_pmpmeas.mod differ diff --git a/src/meas.cc b/src/meas.cc new file mode 100644 index 0000000..3d4bd1d --- /dev/null +++ b/src/meas.cc @@ -0,0 +1,76 @@ +/* ------- + * PMPMEAS + * ------- + * + * Copyright 2022 Dirk Pleiter (pleiter@kth.se) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 3. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "meas.h" + +using namespace std; +using namespace PMPMEAS; + +PapiInf Meas::_papi; +PerfInf Meas::_perf; + +/* + * Dump measurement results + */ + +void Meas::dump(FILE* fp) +{ + fprintf(fp, "Tag: %s\n", _tag.c_str()); + fprintf(fp,"Nmeas: %d\n", nmeas()); + fprintf(fp, "Avg. Weight: %.4e\n", avweight()); + for (int i = 0; i < _cnt; i++) + { + const char* prefix = ""; + switch (_type()) + { + case MeasType::PAPI: + prefix = "PAPI="; + break; + case MeasType::PERF: + prefix = "PERF="; + break; + } + fprintf(fp, "Type[%d]: %s%s\n", i, prefix, _type.typestr(i)); + + fprintf(fp, "Min[%d]: %.4e\n", i, min(i)); + fprintf(fp, "Mean[%d]: %.4e\n", i, mean(i)); + fprintf(fp, "Max[%d]: %.4e\n", i, max(i)); + } + fprintf(fp, "\n"); +} diff --git a/src/meas.h b/src/meas.h new file mode 100644 index 0000000..d22f76c --- /dev/null +++ b/src/meas.h @@ -0,0 +1,345 @@ +/* ------- + * PMPMEAS + * ------- + * + * Copyright 2022 Dirk Pleiter (pleiter@kth.se) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 3. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PMPMEAS_MEAS_H +#define PMPMEAS_MEAS_H + +#include +#include +#include +#include +#include +#include +#include "meastypes.h" +#include "papiinf.h" +#include "perfinf.h" +#include "utils.h" + +namespace PMPMEAS { + +class Meas +{ +private: + std::string _tag; //!< User defined tag + MeasType _type; //!< Type of counters + static PapiInf _papi; //!< Reference to PAPI context + static PerfInf _perf; //!< Reference to perf context + int _cnt; //!< Number of counters + float _cweight; //!< Current weight + float _avweight; //!< Average weight + std::vector _t[2]; //!< Counter values (0=start, 1=end) + std::vector _mean; //!< Average counter values + std::vector _min; //!< Minimum counter values + std::vector _max; //!< Maximum counter values + int _nmeas; //!< Number of measurements + std::vector _vals; //!< Counter values + +public: + Meas(const char* tag, MeasType type) + : _tag(tag), _type(type), _cweight(0), _avweight(0), _nmeas(0) + { + if (type() == MeasType::PAPI) + { + if (_papi.nevent() == 0) + { + for (int i = 0; i < type.cnt(); i++) + { + _papi.create(_type.typestr(i)); + _cnt++; + } + } + _cnt = _papi.nevent(); + } + else if (type() == MeasType::PERF) + { + if (_perf.nevent() == 0) + { + for (int i = 0; i < type.cnt(); i++) + { + _perf.create(_type.typestr(i)); + _cnt++; + } + } + _cnt = _perf.nevent(); + } + + else + { + _cnt = 1; + } + + _t[0].resize(_cnt); + _t[1].resize(_cnt); + _mean.resize(_cnt); + _min.resize(_cnt); + _max.resize(_cnt); + _vals.resize(_cnt); + + for (int i = 0; i < _cnt; i++) + { + _t[0][i] = 0; + _t[1][i] = 0; + _min[i] = std::numeric_limits::max(); + _max[i] = 0; + _vals[i] = 0; + } + } + + inline const string tag(void) const + { + return _tag; + } + + inline void start() + { + _get(0); + } + + // YOU ARE HERE - TODO remove copy operator on return + //inline std::vector read() + inline long long* read() + { + _read(); + return(_vals.data()); + } + + inline void stop(float weight = 1.0) + { + _cweight = weight; + _get(1); + } + + void dump(FILE *fp); + + double mean(int i=0) const + { + return _mean[i] / _nmeas; + } + + double min(int i=0) const + { + return _min[i]; + } + + double max(int i=0) const + { + return _max[i]; + } + + int nmeas() const + { + return _nmeas; + } + + float avweight() const + { + return _avweight / _nmeas; + } + + int cnt() const + { + return _cnt; + } + + int type() const + { + return _type(); + } + + const char* ename(int i) const + { + const char *ret; + switch (_type()) + { + case (MeasType::PAPI): + ret = _papi.ename(i); + break; + case (MeasType::PERF): + ret = _perf.ename(i); + break; + default: // TIME or unrecognized + break; + } + + return ret; + } + +private: + void _read(void) + { + switch(_type()) + { + case MeasType::TIME_BOOT: + { break; } + + case MeasType::TIME_CPU: + { break; } + + case MeasType::TIME_THRD: + { break; } + + case MeasType::PAPI: + { + _papi.read(); + for (int i=0; i<_cnt; ++i) + _vals[i] = _papi.eval(i); + break; + } + + case MeasType::PERF: + { + _perf.pread(); + for (int i=0; i<_cnt; ++i) + _vals[i] = _perf.eval(i); + break; + } + + default: + #ifdef RTRACE_SUPPORT + char err_msg[100]; + snprintf(err_msg, 100, "Internal error (%s,%d)\n", __FILE__, __LINE__); + report_and_exit(err_msg); + #else + fprintf(stderr, "Internal error (%s,%d)\n", __FILE__, __LINE__); + exit(1); + #endif /* ifdef rTrace */ + } + + } + + void _get(int i) + { + assert (i == 0 || i == 1); + + switch(_type()) + { + case MeasType::TIME_BOOT: + { + struct timespec ts; + clock_gettime(CLOCK_BOOTTIME, &ts); + _t[i][0] = ts.tv_sec * 1000000000ULL + ts.tv_nsec; + break; + } + + case MeasType::TIME_CPU: + { + struct timespec ts; + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); + _t[i][0] = ts.tv_sec * 1000000000ULL + ts.tv_nsec; + break; + } + + case MeasType::TIME_THRD: + { + struct timespec ts; + clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts); + _t[i][0] = ts.tv_sec * 1000000000ULL + ts.tv_nsec; + break; + } + + case MeasType::PAPI: + { + if (i == 0) + { + _papi.start(); + for (int j = 0; j < _cnt; j++) + _t[0][j] = 0; + } + else + { + _papi.stop(); + for (int j = 0; j < _cnt; j++) + { + _t[1][j] = _papi.eval(j); + } + } + break; + } + + case MeasType::PERF: + { + if (i == 0) + { + _perf.start(); + for (int j = 0; j < _cnt; j++) + _t[0][j] = 0; + } + else + { + _perf.stop(); + for (int j = 0; j < _cnt; j++) + { + _t[1][j] = _perf.eval(j); + } + } + break; + } + + default: + #ifdef RTRACE_SUPPORT + char err_msg[100]; + snprintf(err_msg, 100, "Internal error (%s,%d)\n", __FILE__, __LINE__); + report_and_exit(err_msg); + #else + fprintf(stderr, "Internal error (%s,%d)\n", __FILE__, __LINE__); + exit(1); + #endif /* ifdef rTrace */ + } + + if (i == 1) + { + for (int j = 0; j < _cnt; j++) + { + double d = (_t[1][j] - _t[0][j]) * _cweight; + _mean[j] += d; + if (d < _min[j]) + _min[j] = d; + if (d > _max[j]) + _max[j] = d; + } + + _avweight += _cweight; + _nmeas++; + } + } + +}; + +} + +#endif diff --git a/src/meastypes.h b/src/meastypes.h new file mode 100644 index 0000000..e81feb3 --- /dev/null +++ b/src/meastypes.h @@ -0,0 +1,172 @@ +/* ------- + * PMPMEAS + * ------- + * + * Copyright 2022 Dirk Pleiter (pleiter@kth.se) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 3. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PMPMEAS_MEASTYPES_H +#define PMPMEAS_MEASTYPES_H + +#include +#include +#include +#include +#include +#include "utils.h" + +using namespace std; + +namespace PMPMEAS { + +class MeasType +{ +public: + enum Type { + TIME_BOOT, + TIME_CPU, + TIME_THRD, + PAPI, + PERF, + }; + +private: + Type _type; + vector _subtype; + +public: + MeasType(Type type) + : _type(type) + { + _subtype.resize(1); + switch(_type) + { + case TIME_BOOT: + _subtype[0] = "TIME_BOOT"; + break; + case TIME_CPU: + _subtype[0] = "TIME_CPU"; + break; + case TIME_THRD: + _subtype[0] = "TIME_THRD"; + break; + default: + _subtype[0] = ""; + break; + } + } + + MeasType(char* type_str) + { + if (strncmp(type_str, "TIME_BOOT", 9) == 0) + { + _type = TIME_BOOT; + _subtype.resize(1); + _subtype[0] = type_str; + } + else if (strncmp(type_str, "TIME_CPU", 8) == 0) + { + _type = TIME_CPU; + _subtype.resize(1); + _subtype[0] = type_str; + } + else if (strncmp(type_str, "TIME_THRD", 9) == 0) + { + _type = TIME_THRD; + _subtype.resize(1); + _subtype[0] = type_str; + } + else if (strncmp(type_str, "PAPI=", 5) == 0) + { + _type = PAPI; + char *c1 = (char *) &type_str[5]; + do { + char *c0 = c1; + for (; (*c1 != '\0') && (*c1 != ','); c1++); + if (*c1 == ',') { + *c1 = '\0'; + _subtype.push_back(string(c0)); + } + else { + _subtype.push_back(string(c0)); + break; + } + } while (c1++); + } + else if (strncmp(type_str, "PERF=", 5) == 0) + { + _type = PERF; + char *c1 = (char *) &type_str[5]; + do { + char *c0 = c1; + for (; (*c1 != '\0') && (*c1 != ','); c1++); + if (*c1 == ',') { + *c1 = '\0'; + _subtype.push_back(string(c0)); + } + else { + _subtype.push_back(string(c0)); + break; + } + } while (c1++); + } + else + { + #ifdef RTRACE_SUPPORT + char err_msg[100]; + snprintf(err_msg, 100, "[PMPMEAS] Unknown measurement type \"%s\"\n", type_str); + report_and_exit(err_msg); + #else + fprintf(stderr, "[PMPMEAS] Unknown measurement type \"%s\"\n", type_str); + exit(1); + #endif /* ifdef rTrace */ + } + } + + const MeasType::Type operator()() const { + return _type; + } + + const int cnt() const { + return _subtype.size(); + } + + const char* typestr(int i) const { + return _subtype[i].c_str(); + } +}; + +} + +#endif \ No newline at end of file diff --git a/src/papiinf.cc b/src/papiinf.cc new file mode 100644 index 0000000..9510ed0 --- /dev/null +++ b/src/papiinf.cc @@ -0,0 +1,203 @@ +/* ------- + * PMPMEAS + * ------- + * + * Copyright 2022 Dirk Pleiter (pleiter@kth.se) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 3. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "papiinf.h" +#include "utils.h" + +using namespace PMPMEAS; + +int PapiInf::_cnt = 0; + +PapiInf::PapiInf(void) +{ + int ret; + +#if USEPAPI + _cnt++; + if (_cnt > 1) + { + #ifdef RTRACE_SUPPORT + report_and_exit("At most one object of class PapiInf must be instantiated!\n"); + #else + fprintf(stderr, "At most one object of class PapiInf must be instantiated!\n"); + exit(1); + #endif /* ifdef rTrace */ + } + + if (PAPI_library_init(PAPI_VER_CURRENT) != PAPI_VER_CURRENT) + { + #ifdef RTRACE_SUPPORT + report_and_exit("PAPI library init error!\n"); + #else + fprintf(stderr, "PAPI library init error!\n"); + exit(1); + #endif /* ifdef rTrace */ + } + + _ctx = PAPI_NULL; + ret = PAPI_create_eventset(&_ctx); + if (ret != PAPI_OK) + { + #ifdef RTRACE_SUPPORT + char err_msg[100]; + snprintf(err_msg, 100, "Failed to create event set (%s)\n", PAPI_strerror(ret)); + report_and_exit(err_msg); + #else + fprintf(stderr, "Failed to create event set (%s)\n", PAPI_strerror(ret)); + exit(1); + #endif /* ifdef rTrace */ + } +#endif + + _nevent = 0; +} + +int PapiInf::create(const std::string& ename) +{ + int ret; + +#if USEPAPI + if (_nevent == PAPICNTMAX) + { + #ifdef RTRACE_SUPPORT + report_and_exit("Exceeding upper limit of number of PAPI events\n"); + #else + fprintf(stderr, "Exceeding upper limit of number of PAPI events\n"); + exit(1); + #endif /* ifdef rTrace */ + } + + ret = PAPI_add_named_event(_ctx, (char*) ename.c_str()); + if (ret != PAPI_OK) + { + #ifdef RTRACE_SUPPORT + char err_msg[100]; + snprintf(err_msg, 100, "WARNING: PAPI_add_named_event failed (%s,\"%s\")\n", + PAPI_strerror(ret), ename.c_str()); + report_and_exit(err_msg); + #else + fprintf(stderr, "WARNING: PAPI_add_named_event failed (%s,\"%s\")\n", + PAPI_strerror(ret), ename.c_str()); + return -1; + #endif /* ifdef rTrace */ + } + + _ename[_nevent] = ename.c_str(); + _nevent++; +//fprintf(stderr, "DEBUG[%s,%d]: ename=%s, nevent=%d\n", __FILE__, __LINE__, ename.c_str(), _nevent); + + return (_nevent - 1); +#else + return 0; +#endif +} + +void PapiInf::cleanup() +{ + int ret; + +#if USEPAPI + ret = PAPI_cleanup_eventset(_ctx); + if (ret != PAPI_OK) + { + #ifdef RTRACE_SUPPORT + char err_msg[100]; + snprintf(err_msg, 100, "PAPI_cleanup_eventset failed (%s)\n", PAPI_strerror(ret)); + report_and_exit(err_msg); + #else + fprintf(stderr, "PAPI_cleanup_eventset failed (%s)\n", PAPI_strerror(ret)); + exit(1); + #endif /* ifdef rTrace */ + } +#endif + + _nevent = 0; +} + +void PapiInf::start(void) +{ +#if USEPAPI + if (PAPI_start(_ctx) != PAPI_OK) + { + #ifdef RTRACE_SUPPORT + report_and_exit("PAPI_start failed\n"); + #else + fprintf(stderr, "PAPI_start failed\n"); + exit(1); + #endif /* ifdef rTrace */ + } +#endif +} + +void PapiInf::stop(void) +{ + int ret; + +#if USEPAPI + ret = PAPI_stop(_ctx, _eval); + if (ret != PAPI_OK) + { + #ifdef RTRACE_SUPPORT + report_and_exit("PAPI_stop failed\n"); + #else + fprintf(stderr, "PAPI_stop failed\n"); + exit(1); + #endif /* ifdef rTrace */ + } +#endif +} + +void PapiInf::read(void) +{ + int ret; + +#if USEPAPI + ret = PAPI_read(_ctx, _eval); + if (ret != PAPI_OK) + { + #ifdef RTRACE_SUPPORT + char err_msg[100]; + snprintf(err_msg, 100, "PAPI_read failed (%s)\n", PAPI_strerror(ret)); + report_and_exit(err_msg); + #else + fprintf(stderr, "PAPI_read failed (%s)\n", PAPI_strerror(ret)); + exit(1); + #endif /* ifdef rTrace */ + } +#endif +} diff --git a/src/papiinf.h b/src/papiinf.h new file mode 100644 index 0000000..99849ee --- /dev/null +++ b/src/papiinf.h @@ -0,0 +1,96 @@ +/* ------- + * PMPMEAS + * ------- + * + * Copyright 2022 Dirk Pleiter (pleiter@kth.se) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 3. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PMPMEAS_PAPIINF_H +#define PMPMEAS_PAPIINF_H + +#include +#include + +namespace PMPMEAS { + +class Inf{ +private: + std::string _ename[PAPICNTMAX]; //!< Event name + +public: + const char* ename(int i) const + { + return _ename[i].c_str(); + } +}; + +class PapiInf:Inf +{ +private: + static int _cnt; + + int _ctx; + int _nevent; //!< Number of events + std::string _ename[PAPICNTMAX]; //!< Event name + long long _eval[PAPICNTMAX]; //!< Event value + +public: + PapiInf(void); + + int create(const std::string&); + void cleanup(); + + void start(void); + void stop(void); + void read(void); + + long long eval(int i) const + { + return _eval[i]; + } + + const char* ename(int i) const + { + return _ename[i].c_str(); + } + + int nevent() const + { + return _nevent; + } +}; + +} + +#endif diff --git a/src/perfinf.cc b/src/perfinf.cc new file mode 100644 index 0000000..70faa18 --- /dev/null +++ b/src/perfinf.cc @@ -0,0 +1,245 @@ +/* ------- + * PMPMEAS + * ------- + * + * Copyright 2022 Dirk Pleiter (pleiter@kth.se) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 3. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Code for access to perf counters +*/ + +#include "perfinf.h" +#include +#include +#include +#include +#include +#include +#include "utils.h" + +int PerfInf::_cnt = 0; + +struct read_format { + uint64_t nr; + struct { + uint64_t value; + uint64_t id; + } values[]; +}; + + +PerfInf::PerfInf(void) +{ + int ret; + + _cnt++; + if (_cnt > 1) + { + #ifdef RTRACE_SUPPORT + report_and_exit("At most one object of class PerfInf must be instantiated!\n"); + #else + fprintf(stderr, "At most one object of class PerfInf must be instantiated!\n"); + exit(1); + #endif /* ifdef rTrace */ + } + + _nevent = 0; +} + + +int PerfInf::create(const std::string& ename) +{ + if (_nevent >= PERF_CNTMAX) { + #ifdef RTRACE_SUPPORT + report_and_exit("Maximum number of PerfInf events exceeded\n"); + #else + fprintf(stderr, "Maximum number of PerfInf events exceeded\n"); + exit(1); + #endif /* ifdef rTrace */ + } + + struct perf_event_attr pea; + memset(&pea, 0, sizeof(struct perf_event_attr)); + + pea.size = sizeof(struct perf_event_attr); + + if (0) {} +# define xx(a, b, c) else if (ename == #a) { pea.type = b; pea.config = c; } +# include "perfinftypesxx.h" + else + { + #ifdef RTRACE_SUPPORT + char err_msg[100]; + snprintf(err_msg, 100, "Unknown perf counter type \"%s\"\n", ename.c_str()); + report_and_exit(err_msg); + #else + fprintf(stderr, "Unknown perf counter type \"%s\"\n", ename.c_str()); + exit(1); + #endif /* ifdef rTrace */ + } + + pea.disabled = 1; + pea.exclude_kernel = 1; + pea.exclude_hv = 1; + pea.read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID; + + if (_nevent == 0) { + _fd[0] = syscall(__NR_perf_event_open, &pea, 0, -1, -1, 0); + } + else { + _fd[_nevent] = syscall(__NR_perf_event_open, &pea, 0, -1, _fd[0], 0); + } + if (_fd[_nevent] == -1) { + #ifdef RTRACE_SUPPORT + char err_msg[100]; + snprintf(err_msg, 100, "WARNING: PerfInf failed to create event (ename=%s, config=0x%llx)\n", ename.c_str(), pea.config); + report_and_exit(err_msg); + #else + fprintf(stderr, "WARNING: PerfInf failed to create event (ename=%s, config=0x%llx)\n", ename.c_str(), pea.config); + return -1; + #endif /* ifdef rTrace */ + } + + if (ioctl(_fd[_nevent], PERF_EVENT_IOC_ID, &_eid[_nevent]) != 0) + { + #ifdef RTRACE_SUPPORT + report_and_exit("ioctl failed\n"); + #else + fprintf(stderr, "ioctl failed\n"); + exit(1); + #endif /* ifdef rTrace */ + } + + _nevent++; + + return (_nevent - 1); +} + +void PerfInf::cleanup(void) +{ + int i; + + for (i = 0; i < _nevent; i++) + close(_fd[_nevent]); +} + + +void PerfInf::start(void) +{ + if (_nevent > 0) { + ioctl(_fd[0], PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP); + ioctl(_fd[0], PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP); + } +} + + +void PerfInf::stop(void) +{ + if (_nevent > 0) { + if (ioctl(_fd[0], PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP) != 0) + { + #ifdef RTRACE_SUPPORT + report_and_exit("ioctl failed\n"); + #else + fprintf(stderr, "ioctl failed\n"); + exit(1); + #endif /* ifdef rTrace */ + } + if (read(_fd[0], _buf, sizeof(_buf)) == -1) + { + #ifdef RTRACE_SUPPORT + report_and_exit("read failed\n"); + #else + fprintf(stderr, "read failed\n"); + exit(1); + #endif /* ifdef rTrace */ + } + + for (int j = 0; j < _nevent; j++) + _eval[j] = 0; + + struct read_format* rf = (struct read_format*) _buf; + for (int i = 0; i < rf->nr; i++) + for (int j = 0; j < _nevent; j++) + if (rf->values[i].id == _eid[j]) { + _eval[j] = rf->values[i].value; + } + } +} + +// YOU ARE HERE +void PerfInf::pread(void) +{ + if (_nevent > 0) { + if (ioctl(_fd[0], PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP) != 0) + { + #ifdef RTRACE_SUPPORT + report_and_exit("ioctl disable failed\n"); + #else + fprintf(stderr, "ioctl disable failed\n"); + exit(1); + #endif /* ifdef rTrace */ + } + if (read(_fd[0], _buf, sizeof(_buf)) == -1) + { + #ifdef RTRACE_SUPPORT + report_and_exit("read failed\n"); + #else + fprintf(stderr, "read failed\n"); + exit(1); + #endif /* ifdef rTrace */ + } + + for (int j = 0; j < _nevent; j++) + _eval[j] = 0; + + struct read_format* rf = (struct read_format*) _buf; + for (int i = 0; i < rf->nr; i++) + for (int j = 0; j < _nevent; j++) + if (rf->values[i].id == _eid[j]) { + _eval[j] = rf->values[i].value; + } + + if (ioctl(_fd[0], PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP) != 0) + { + #ifdef RTRACE_SUPPORT + report_and_exit("ioctl enable failed\n"); + #else + fprintf(stderr, "ioctl enable failed\n"); + exit(1); + #endif /* ifdef rTrace */ + } + } +} diff --git a/src/perfinf.h b/src/perfinf.h new file mode 100644 index 0000000..32b2f96 --- /dev/null +++ b/src/perfinf.h @@ -0,0 +1,100 @@ +/* ------- + * PMPMEAS + * ------- + * + * Copyright 2022 Dirk Pleiter (pleiter@kth.se) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 3. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Code for access to perf counters +*/ + +#ifndef PMPMEAS_PERFINF_H +#define PMPMEAS_PERFINF_H + +#include +#include +#include + +#define PERF_CNTMAX 5 //!< Maximum number of events + +class PerfInf +{ +public: + enum Type { +# define xx(a, b, c) a, +# include "perfinftypesxx.h" + }; + +private: + static int _cnt; //!< Number of instances (must be 0 or 1) + + int _nevent; + int _fd[PERF_CNTMAX]; + std::string _ename[PAPICNTMAX]; //!< Event name + uint64_t _eid[PERF_CNTMAX]; //!< Event ID + uint64_t _eval[PERF_CNTMAX]; //!< Event value + + char* _buf[4096]; + +public: + PerfInf(void); + + int create(const std::string&); + void cleanup(); + + void start(void); + void stop(void); + void pread(void); + + uint64_t eval(int i) const + { + return _eval[i]; + } + + const char* ename(int i) const + { + return _ename[i].c_str(); + } + + int nevent() const + { + return _nevent; + } + +private: + //long _perf_event_open(struct perf_event_attr *, pid_t, int, int, unsigned long); +}; + +#endif diff --git a/src/perfinftypesxx.h b/src/perfinftypesxx.h new file mode 100644 index 0000000..3caae1c --- /dev/null +++ b/src/perfinftypesxx.h @@ -0,0 +1,57 @@ +/* ------- + * PMPMEAS + * ------- + * + * Copyright 2022 Dirk Pleiter (pleiter@kth.se) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 3. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// PMPMEAS name, perf type, perf config +// See: /usr/include/linux/perf_event.h and https://github.com/efficient/memc3/blob/master/perf_count.c + +xx(cycles, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES) +xx(ref_cycles, PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES) + +xx(L1_dcache_loads, PERF_TYPE_HW_CACHE, (PERF_COUNT_HW_CACHE_L1D | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))) +xx(L1_dcache_load_misses, PERF_TYPE_HW_CACHE, (PERF_COUNT_HW_CACHE_L1D | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))) + +xx(L1_dcache_stores, PERF_TYPE_HW_CACHE, (PERF_COUNT_HW_CACHE_L1D | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))) + +xx(LLC_loads, PERF_TYPE_HW_CACHE, (PERF_COUNT_HW_CACHE_LL | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))) +xx(LLC_load_misses, PERF_TYPE_HW_CACHE, (PERF_COUNT_HW_CACHE_LL | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))) +xx(LLC_stores, PERF_TYPE_HW_CACHE, (PERF_COUNT_HW_CACHE_LL | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))) + +xx(dTLB_loads, PERF_TYPE_HW_CACHE, (PERF_COUNT_HW_CACHE_DTLB | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))) +xx(dTLB_load_misses, PERF_TYPE_HW_CACHE, (PERF_COUNT_HW_CACHE_DTLB | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))) + +#undef xx diff --git a/src/pmpmeas-api.c b/src/pmpmeas-api.c new file mode 100644 index 0000000..8653271 --- /dev/null +++ b/src/pmpmeas-api.c @@ -0,0 +1,82 @@ +/* ------- + * PMPMEAS + * ------- + * + * Copyright 2022 Dirk Pleiter (pleiter@kth.se) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 3. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "pmpmeas-api.h" +#include "pmpmeas.h" + +void pmpmeas_init() +{ + pmpmeas__init(); +} + +void pmpmeas_start(const char* tag) +{ + pmpmeas__start(tag); +} + +void pmpmeas_read_init(long long **vals, int *n) +{ + pmpmeas__read_init(vals, n); +} + +void pmpmeas_read(long long *vals) +{ + pmpmeas__read(vals); +} + +void pmpmeas_read_finalize() +{ + pmpmeas__read_finalize(); +} + +void pmpmeas_stop(float weight) +{ + pmpmeas__stop(weight); +} + +void pmpmeas_stop_fortran(float *weight) +{ + pmpmeas__stop(*weight); +} + +void pmpmeas_finish() +{ + pmpmeas__finish(); +} diff --git a/src/pmpmeas-api.h b/src/pmpmeas-api.h new file mode 100644 index 0000000..dc6faf1 --- /dev/null +++ b/src/pmpmeas-api.h @@ -0,0 +1,59 @@ +/* ------- + * PMPMEAS + * ------- + * + * Copyright 2022 Dirk Pleiter (pleiter@kth.se) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 3. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PMPMEAS_API_H +#define PMPMEAS_API_H + +#ifdef __cplusplus +extern "C" { +#endif + +void pmpmeas_init(); +void pmpmeas_start(const char*); +void pmpmeas_read_init(long long**, int*); +void pmpmeas_read(long long*); +void pmpmeas_read_finalize(); +void pmpmeas_stop(float); +void pmpmeas_stop_fortran(float*); +void pmpmeas_finish(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/pmpmeas.cc b/src/pmpmeas.cc new file mode 100644 index 0000000..a015b78 --- /dev/null +++ b/src/pmpmeas.cc @@ -0,0 +1,221 @@ +/* ------- + * PMPMEAS + * ------- + * + * Copyright 2022 Dirk Pleiter (pleiter@kth.se) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 3. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include "pmpmeas.h" +#include "meas.h" +#include "utils.h" + +using namespace std; +using namespace PMPMEAS; + +// YOU ARE HERE +static list pmpmeas_type_lst; +static list pmpmeas_meas_lst; +static list pmpmeas_match_lst; + +int pmpmeas_meas_cnt_total; +long long *pmpmeas_meas_vals; + +#define LENGTH_ERR_MSG 1280 + +string ctag; + +time_t tstart; + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Library initialisation function + */ + +void pmpmeas__init() +{ + tstart = time(NULL); + + char* t = getenv("PMPMEAS_MEAS_TYPES"); + if (t != NULL) { + char *c1 = t; + do { + char *c0 = c1; + for (; (*c1 != '\0') && (*c1 != ';'); c1++); + if (*c1 == ';') { + *c1 = '\0'; + pmpmeas_type_lst.push_back(new MeasType(c0)); + } + else { + pmpmeas_type_lst.push_back(new MeasType(c0)); + break; + } + } while (c1++); + } +} + +/* + * Start measurement + */ + +void pmpmeas__start(const char *tag) +{ + ctag = tag; + + pmpmeas_match_lst.clear(); + + for (list::iterator m = pmpmeas_meas_lst.begin(); m != pmpmeas_meas_lst.end(); m++) + if ((*m)->tag() == ctag) + pmpmeas_match_lst.push_back(*m); + + if (pmpmeas_match_lst.empty()) + for (list::iterator mt = pmpmeas_type_lst.begin(); mt != pmpmeas_type_lst.end(); mt++) + { + Meas *m = new Meas(tag, *(*mt)); + pmpmeas_meas_lst.push_back(m); + pmpmeas_match_lst.push_back(m); + + } + + for (list::iterator m = pmpmeas_match_lst.begin(); m != pmpmeas_match_lst.end(); m++) + (*m)->start(); + +} + + +// YOU ARE HERE +void pmpmeas__read_init(long long **vals, int *n) +{ + bool tmp = pmpmeas_match_lst.empty(); + + if (pmpmeas_match_lst.empty()) + for (list::iterator mt = pmpmeas_type_lst.begin(); mt != pmpmeas_type_lst.end(); mt++) + { + Meas *m = new Meas("PLACEHOLDER", *(*mt)); + pmpmeas_match_lst.push_back(m); + } + + pmpmeas_meas_cnt_total=0; + for (list::iterator m = pmpmeas_match_lst.begin(); m != pmpmeas_match_lst.end(); m++) + pmpmeas_meas_cnt_total += (*m)->cnt(); + pmpmeas_meas_vals = (long long *) malloc(pmpmeas_meas_cnt_total*sizeof(*pmpmeas_meas_vals)); + + *vals = pmpmeas_meas_vals; + *n = pmpmeas_meas_cnt_total; + + if (tmp) + pmpmeas_match_lst.clear(); + + //printf("ncnt = %d\n", pmpmeas_meas_cnt_total); // DEBUGGING +} + +// YOU ARE HERE +void pmpmeas__read(long long *vals) +{ + int index = 0; + if (vals==NULL) // Default to global + vals = pmpmeas_meas_vals; + + for (list::iterator m = pmpmeas_meas_lst.begin(); m != pmpmeas_meas_lst.end(); m++){ + memcpy( &vals[index], (*m)->read(), (*m)->cnt()*sizeof(*pmpmeas_meas_vals)); + index += (*m)->cnt(); + } +} + +// YOU ARE HERE +void pmpmeas__read_finalize() +{ + free(pmpmeas_meas_vals); +} + +void pmpmeas__stop(float weight) +{ + for (list::iterator m = pmpmeas_match_lst.begin(); m != pmpmeas_match_lst.end(); m++) + (*m)->stop(weight); +} + +void pmpmeas__finish() +{ + const int len = 1024; + struct tm * timeinfo; + char buf[len]; + char fname[len]; + pid_t pid = getpid(); + + snprintf(fname, len, "pmpmeas_%06d_XXXXXX", pid); + int ret = mkstemp(fname); + FILE *fp = fopen(fname, "w"); + if (fp == NULL) + { + #ifdef RTRACE_SUPPORT + char err_msg[LENGTH_ERR_MSG]; + snprintf(err_msg, LENGTH_ERR_MSG, "Failed to open file \"%s\" for writing\n", fname); + report_and_exit(err_msg); + #else + fprintf(stderr, "Failed to open file \"%s\" for writing\n", fname); + exit(1); + #endif /* ifdef rTrace */ + } + + timeinfo = localtime(&tstart); + strftime (buf, len, "%F %T", timeinfo); + fprintf(fp, "Start: %s\n", buf); + fprintf(fp, "\n"); + + gethostname(buf, len); + fprintf(fp, "Hostname: %s\n", buf); + fprintf(fp, "\n"); + + for (list::iterator m = pmpmeas_meas_lst.begin(); m != pmpmeas_meas_lst.end(); m++) + (*m)->dump(fp); + + time_t tend = time(NULL); + timeinfo = localtime(&tend); + strftime (buf, len, "%F %T", timeinfo); + fprintf(fp, "End: %s\n", buf); + + fclose(fp); +} + +#ifdef __cplusplus +} +#endif diff --git a/src/pmpmeas.h b/src/pmpmeas.h new file mode 100644 index 0000000..aca354c --- /dev/null +++ b/src/pmpmeas.h @@ -0,0 +1,58 @@ +/* ------- + * PMPMEAS + * ------- + * + * Copyright 2022 Dirk Pleiter (pleiter@kth.se) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 3. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PMPMEAS_HH +#define PMPMEAS_HH + +#ifdef __cplusplus +extern "C" { +#endif + +void pmpmeas__init(); +void pmpmeas__start(const char*); +void pmpmeas__read_init(long long**, int*); +void pmpmeas__read(long long*); +void pmpmeas__read_finalize(); +void pmpmeas__stop(float); +void pmpmeas__finish(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/rTrace.cpp b/src/rTrace.cpp index f762db5..e48d889 100644 --- a/src/rTrace.cpp +++ b/src/rTrace.cpp @@ -27,6 +27,7 @@ #include #include #include +#include "utils.h" // getpid #include @@ -37,8 +38,12 @@ #include // PMPMEAS +#include #include "pmpmeas.h" #include "meas.h" +#include "meastypes.h" +#include "pmpmeas-api.h" +using namespace PMPMEAS; //#define DEBUG /* Uncomment to enable verbose debug info */ //#define DUMMY_TIMESTEPS /* Uncomment for 1s timestep for each subsequent event call */ @@ -101,6 +106,9 @@ static int NUM_METRICS=0; ///* Number of metrics, only applicable if COLLECT_ME static long long *pmpmeas_vals; static int pmpmeas_n; static OTF2_Type *typeIDs; +std::list pmpmeas_type_lst; +std::list pmpmeas_meas_lst; +std::list pmpmeas_match_lst; // DEBUGGING static FILE *fp; ///* Log file on server proc @@ -111,7 +119,7 @@ char log_filename[]="log.log"; ///* Name of log file on server proc // Function declarations /////////////////////////////// // R client functions (master/slaves) -RcppExport int init_otf2_logger(int, Rcpp::String, Rcpp::String, bool); +//RcppExport int init_otf2_logger(int, Rcpp::String, Rcpp::String, bool); RcppExport SEXP finalize_GlobalDefWriter_client(); RcppExport int define_otf2_regionRef_client(Rcpp::String, int); RcppExport SEXP evtWriter_MeasurementOnOff_client(bool); @@ -150,13 +158,10 @@ int get_regionRef_array_server(OTF2_RegionRef, void*); void free_regionRef_array_server(); void globalDefWriter_metrics_server(); - // Helper functions for debugging -void report_and_exit(const char*, void *sock=NULL); void fupdate_server(FILE*, const char*); RcppExport SEXP print_errnos(); - /////////////////////////////// // Function definitions /////////////////////////////// @@ -280,7 +285,7 @@ RcppExport int init_otf2_logger(int max_nprocs, Rcpp::String archivePath = "./rT fupdate_server(fp, "Init of otf2 objs complete\n"); // Init zmq context - context = zmq_ctx_new (); + context = zmq_ctx_new(); if (COLLECT_METRICS){ // Server creates metrics from pmpmeas objects @@ -1007,14 +1012,14 @@ void globalDefWriter_metrics_server() OTF2_ErrorCode ret; // Meas contains all metrics of specific type (eg time, papi, perf) - for (list::iterator m = pmpmeas_match_lst.begin(); m != pmpmeas_match_lst.end(); m++){ - switch( (*m)->_type() ) + for (std::list::iterator m = pmpmeas_match_lst.begin(); m != pmpmeas_match_lst.end(); m++){ + switch( (*m)->type() ) { case (MeasType::PAPI): metricType = OTF2_METRIC_TYPE_PAPI; break; case (MeasType::PERF): - metricType = OTF2_METRIC_TYPE_PERF; + metricType = OTF2_METRIC_TYPE_OTHER; // perf break; default: // TIME or unrecognized continue; @@ -1022,13 +1027,13 @@ void globalDefWriter_metrics_server() } // Cycle through each metric of given type, and create metric - for ( int i=0; i<(*m)->ncnt(); i++ ){ - char *ename = (*m)->ename(i); + for ( int i=0; i<(*m)->cnt(); i++ ){ + const char *ename = (*m)->ename(i); Rcpp::String stringEname(ename); stringRef_name = globalDefWriter_WriteString_server(stringEname); - ret = OTF2_GlobalDefWriter_WriteMetricMember(globalDefWriter, + ret = OTF2_GlobalDefWriter_WriteMetricMember(global_def_writer, NUM_METRICS++ /* MetricMemberRef */, stringRef_name, 0 /*stringRef_description*/, @@ -1047,15 +1052,15 @@ void globalDefWriter_metrics_server() OTF2_MetricMemberRef *metricMembers; - metricMembers = (OTF2_MetricMemberRef*)malloc(NUM_METRICS*sizeof(*OTF2_MetricMemberRef)); - typeIDs = (OTF2_Type*)malloc(NUM_METRICS*sizeof(*typeIDs)); + metricMembers = (OTF2_MetricMemberRef*) malloc(NUM_METRICS*sizeof(*metricMembers)); + typeIDs = (OTF2_Type*) malloc(NUM_METRICS*sizeof(*typeIDs)); - for (OTF2_MetricMemberRef i=0; i