1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
|
/*
* Copyright (C) 2014 Artem Polyakov <artpol84@gmail.com>
* Copyright (c) 2014-2017 Intel, Inc. All rights reserved.
* Copyright (c) 2017-2018 Mellanox Technologies Ltd. All rights reserved.
* Copyright (c) 2023 Triad National Security, LLC. All rights
* reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#ifndef OPAL_UTIL_TIMING_H
#define OPAL_UTIL_TIMING_H
#include "opal_config.h"
#include "opal/class/opal_list.h"
#include "opal/runtime/opal_params.h"
typedef enum {
OPAL_TIMING_AUTOMATIC_TIMER,
OPAL_TIMING_GET_TIME_OF_DAY,
OPAL_TIMING_CYCLE_NATIVE,
OPAL_TIMING_USEC_NATIVE
} opal_timer_type_t;
#if OPAL_ENABLE_TIMING
typedef double (*opal_timing_ts_func_t)(void);
# define OPAL_TIMING_STR_LEN 256
typedef struct {
char id[OPAL_TIMING_STR_LEN], cntr_env[OPAL_TIMING_STR_LEN];
int enabled, error;
int cntr;
double ts;
opal_timing_ts_func_t get_ts;
} opal_timing_env_t;
opal_timing_ts_func_t opal_timing_ts_func(opal_timer_type_t type);
void opal_timing_enable_native_timers(void);
void opal_timing_disable_native_timers(void);
# define OPAL_TIMING_ENABLE_NATIVE_TIMERS opal_timing_enable_native_timers()
# define OPAL_TIMING_DISABLE_NATIVE_TIMERS opal_timing_disable_native_timers()
# define OPAL_TIMING_ENV_START_TYPE(func, _nm, type, prefix) \
do { \
char *ptr = NULL; \
char *_prefix = prefix; \
int n; \
if (NULL == prefix) { \
_prefix = ""; \
} \
(_nm)->error = 0; \
n = snprintf((_nm)->id, OPAL_TIMING_STR_LEN, "%s_%s", _prefix, func); \
if (n > OPAL_TIMING_STR_LEN) { \
(_nm)->error = 1; \
} \
n = sprintf((_nm)->cntr_env, "OMPI_TIMING_%s_CNT", (_nm)->id); \
if (n > OPAL_TIMING_STR_LEN) { \
(_nm)->error = 1; \
} \
ptr = getenv((_nm)->id); \
if (NULL == ptr || strcmp(ptr, "1")) { \
(_nm)->enabled = 0; \
} \
(_nm)->get_ts = opal_timing_ts_func(type); \
ptr = getenv("OPAL_TIMING_ENABLE"); \
if (NULL != ptr) { \
(_nm)->enabled = atoi(ptr); \
} \
(_nm)->cntr = 0; \
ptr = getenv((_nm)->id); \
if (NULL != ptr) { \
(_nm)->cntr = atoi(ptr); \
} \
(_nm)->ts = (_nm)->get_ts(); \
if (0 != (_nm)->error) { \
(_nm)->enabled = 0; \
} \
} while (0)
/* We use function names for identification
* however this might be a problem for the private
* functions declared as static as their names may
* conflict.
* Use prefix to do a finer-grained identification if needed
*/
# define OPAL_TIMING_ENV_INIT_PREFIX(prefix, name) \
opal_timing_env_t name##_val, *name = &(name##_val); \
OPAL_TIMING_ENV_START_TYPE(__func__, name, OPAL_TIMING_AUTOMATIC_TIMER, prefix);
# define OPAL_TIMING_ENV_INIT(name) OPAL_TIMING_ENV_INIT_PREFIX("", name)
# define OPAL_TIMING_ENV_NEXT(h, ...) \
do { \
int n; \
char buf1[OPAL_TIMING_STR_LEN], buf2[OPAL_TIMING_STR_LEN]; \
double time; \
char *filename; \
if (h->enabled) { \
/* enabled codepath */ \
time = h->get_ts() - h->ts; \
n = snprintf(buf1, OPAL_TIMING_STR_LEN, "OMPI_TIMING_%s_DESC_%d", h->id, h->cntr); \
if (n > OPAL_TIMING_STR_LEN) { \
h->error = 1; \
} \
n = snprintf(buf2, OPAL_TIMING_STR_LEN, __VA_ARGS__); \
if (n > OPAL_TIMING_STR_LEN) { \
h->error = 1; \
} \
setenv(buf1, buf2, 1); \
n = snprintf(buf1, OPAL_TIMING_STR_LEN, "OMPI_TIMING_%s_VAL_%d", h->id, h->cntr); \
if (n > OPAL_TIMING_STR_LEN) { \
h->error = 1; \
} \
n = snprintf(buf2, OPAL_TIMING_STR_LEN, "%lf", time); \
if (n > OPAL_TIMING_STR_LEN) { \
h->error = 1; \
} \
setenv(buf1, buf2, 1); \
filename = strrchr(__FILE__, '/'); \
filename = (filename == NULL) ? strdup(__FILE__) : filename + 1; \
n = snprintf(buf1, OPAL_TIMING_STR_LEN, "OMPI_TIMING_%s_FILE_%d", h->id, h->cntr); \
if (n > OPAL_TIMING_STR_LEN) { \
h->error = 1; \
} \
n = snprintf(buf2, OPAL_TIMING_STR_LEN, "%s", filename); \
if (n > OPAL_TIMING_STR_LEN) { \
h->error = 1; \
} \
setenv(buf1, buf2, 1); \
h->cntr++; \
sprintf(buf1, "%d", h->cntr); \
setenv(h->cntr_env, buf1, 1); \
/* We don't include env operations into the consideration. \
* Hopefully this will help to make measurements more accurate. \
*/ \
h->ts = h->get_ts(); \
} \
if (h->error) { \
n = snprintf(buf1, OPAL_TIMING_STR_LEN, "OMPI_TIMING_%s_ERROR", h->id); \
if (n > OPAL_TIMING_STR_LEN) { \
h->error = 1; \
} \
n = snprintf(buf2, OPAL_TIMING_STR_LEN, "%d", h->error); \
if (n > OPAL_TIMING_STR_LEN) { \
h->error = 1; \
} \
setenv(buf1, buf2, 1); \
} \
} while (0)
/* This function supposed to be called from the code that will
* do the postprocessing, i.e. OMPI timing portion that will
* do the reduction of accumulated values
*/
# define OPAL_TIMING_ENV_CNT_PREFIX(prefix, func, _cnt) \
do { \
char ename[OPAL_TIMING_STR_LEN]; \
char *ptr = NULL; \
int n = snprintf(ename, OPAL_TIMING_STR_LEN, "OMPI_TIMING_%s_%s_CNT", prefix, func); \
(_cnt) = 0; \
if (n <= OPAL_TIMING_STR_LEN) { \
ptr = getenv(ename); \
if (NULL != ptr) { \
(_cnt) = atoi(ptr); \
}; \
} \
} while (0)
# define OPAL_TIMING_ENV_ERROR_PREFIX(prefix, func, _err) \
do { \
char ename[OPAL_TIMING_STR_LEN]; \
(_err) = 0; \
char *ptr = NULL; \
int n = snprintf(ename, OPAL_TIMING_STR_LEN, "OMPI_TIMING_%s%s_ERROR", prefix, func); \
if (n <= OPAL_TIMING_STR_LEN) { \
ptr = getenv(ename); \
if (NULL != ptr) { \
(_err) = atoi(ptr); \
}; \
} \
} while (0)
# define OPAL_TIMING_ENV_GETDESC_PREFIX(prefix, filename, func, i, desc, _t) \
do { \
char vname[OPAL_TIMING_STR_LEN]; \
(_t) = 0.0; \
sprintf(vname, "OMPI_TIMING_%s_%s_FILE_%d", prefix, func, i); \
*filename = getenv(vname); \
sprintf(vname, "OMPI_TIMING_%s_%s_DESC_%d", prefix, func, i); \
*desc = getenv(vname); \
sprintf(vname, "OMPI_TIMING_%s_%s_VAL_%d", prefix, func, i); \
char *ptr = getenv(vname); \
if (NULL != ptr) { \
sscanf(ptr, "%lf", &(_t)); \
} \
} while (0)
# define OPAL_TIMING_ENV_GETDESC(file, func, index, desc) \
OPAL_TIMING_ENV_GETDESC_PREFIX("", file, func, index, desc)
#else
# define OPAL_TIMING_ENABLE_NATIVE_TIMERS
# define OPAL_TIMING_DISABLE_NATIVE_TIMERS
# define OPAL_TIMING_ENV_START_TYPE(func, type, prefix)
# define OPAL_TIMING_ENV_INIT(name)
# define OPAL_TIMING_ENV_INIT_PREFIX(prefix, name)
# define OPAL_TIMING_ENV_NEXT(h, ...)
# define OPAL_TIMING_ENV_CNT_PREFIX(prefix, func)
# define OPAL_TIMING_ENV_CNT(func)
# define OPAL_TIMING_ENV_GETDESC_PREFIX(prefix, func, i, desc)
# define OPAL_TIMING_ENV_GETDESC(func, index, desc)
# define OPAL_TIMING_ENV_ERROR_PREFIX(prefix, func)
#endif
#endif
|