This source file includes following definitions.
- hpctimer_initialize
- hpctimer_finalize
- hpctimer_print_timers
- hpctimer_sanity_check
- hpctimer_wtime
- hpctimer_wtime_gettimeofday
- hpctimer_wtime_tsc
- hpctimer_tsc_initialize
- hpctimer_gettsc
- hpctimer_measure_overhead
- hpctimer_calibrate_sleep
   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 #include <sys/time.h>
  44 #include <unistd.h>
  45 
  46 #include <stdio.h>
  47 #include <stdlib.h>
  48 #include <strings.h>
  49 #include <math.h>
  50 #include <inttypes.h>
  51 
  52 #include <mpi.h>
  53 
  54 #include "hpctimer.h"
  55 
  56 #define NELEMS(v) (sizeof(v) / sizeof((v)[0]))
  57 
  58 
  59 
  60 
  61 
  62 
  63 
  64 
  65 
  66 
  67 
  68 
  69 
  70 
  71 
  72 
  73 
  74 #if defined(__GNUC__)
  75 #   define __inline__ __inline__
  76 #   define __asm__ __asm__
  77 #   define __volatile__ __volatile__
  78 #elif defined(__SUNPRO_C)
  79 #   define __inline__ __inline__
  80 #   define __asm__ __asm__
  81 #   define __volatile__ __volatile__
  82 #endif
  83 
  84 typedef int (*hpctimer_initialize_func_ptr_t)(void);
  85 typedef void (*hpctimer_finalize_func_ptr_t)(void);
  86 typedef int (*hpctimer_isimplemented_func_ptr_t)(void);
  87 typedef double (*hpctimer_wtime_func_ptr_t)(void);
  88 
  89 typedef struct hpctimer {
  90     char *name;
  91     hpctimer_initialize_func_ptr_t initialize;
  92     hpctimer_finalize_func_ptr_t finalize;
  93     hpctimer_isimplemented_func_ptr_t isimplemented;
  94     hpctimer_wtime_func_ptr_t wtime;
  95 } hpctimer_t;
  96 
  97 static uint64_t hpctimer_overhead;  
  98 static uint64_t hpctimer_freq;      
  99 
 100 static double hpctimer_wtime_tsc(void);
 101 static int hpctimer_tsc_initialize(void);
 102 static __inline__ uint64_t hpctimer_gettsc(void);
 103 static uint64_t hpctimer_measure_overhead(void);
 104 static uint64_t hpctimer_calibrate_sleep(uint64_t overhead);
 105 static double hpctimer_wtime_gettimeofday(void);
 106 
 107 
 108 
 109 
 110 static hpctimer_t hpctimer_timers[] = {
 111     {"MPI_Wtime", NULL, NULL, NULL, MPI_Wtime},
 112     {"gettimeofday", NULL, NULL, NULL, hpctimer_wtime_gettimeofday},
 113     {"tsc", hpctimer_tsc_initialize, NULL, NULL, hpctimer_wtime_tsc}
 114 };
 115 
 116 static hpctimer_wtime_func_ptr_t hpctimer_wtime_func_ptr = NULL;
 117 static int hpctimer_timer = -1;
 118 
 119 
 120 int hpctimer_initialize(const char *timername)
 121 {
 122     hpctimer_wtime_func_ptr = NULL;
 123     hpctimer_timer = -1;
 124     unsigned int i;
 125     for (i = 0; i < NELEMS(hpctimer_timers); i++) {
 126         if (hpctimer_timers[i].isimplemented != NULL) {
 127             if (!hpctimer_timers[i].isimplemented()) {
 128                 continue;
 129             }
 130         }
 131         if (strcasecmp(timername, hpctimer_timers[i].name) == 0) {
 132             hpctimer_wtime_func_ptr = hpctimer_timers[i].wtime;
 133             hpctimer_timer = i;
 134             if (hpctimer_timers[i].initialize) {
 135                 return hpctimer_timers[i].initialize();
 136             }
 137             return HPCTIMER_SUCCESS;
 138         }
 139     }
 140     return HPCTIMER_FAILURE;
 141 }
 142 
 143 
 144 void hpctimer_finalize(void)
 145 {
 146     if (hpctimer_timers[hpctimer_timer].finalize) {
 147         hpctimer_timers[hpctimer_timer].finalize();
 148     }
 149     hpctimer_wtime_func_ptr = NULL;
 150 }
 151 
 152 
 153 void hpctimer_print_timers(void)
 154 {
 155     unsigned int i;
 156 
 157     printf("Supported timers:\n");
 158     for (i = 0; i < NELEMS(hpctimer_timers); i++) {
 159         if (hpctimer_timers[i].isimplemented != NULL) {
 160             if (!hpctimer_timers[i].isimplemented()) {
 161                 continue;
 162             }
 163         }
 164         printf("    %s\n", hpctimer_timers[i].name);
 165     }
 166 }
 167 
 168 
 169 
 170 
 171 
 172 int hpctimer_sanity_check(void)
 173 {
 174     enum { NTESTS = 4 };
 175     double start, stop, currtime, prevtime = 0.0, err = 0.05;
 176     int sanity = 1;
 177 
 178     int delay = 0;
 179     for (delay = 1; delay < NTESTS; delay++) {
 180         start = hpctimer_wtime();
 181         sleep(delay);
 182         stop = hpctimer_wtime();
 183         currtime = stop - start;
 184         if (delay > 1) {
 185             if (fabs(prevtime - currtime / delay) > prevtime * err) {
 186                 sanity = 0;
 187             }
 188             
 189 
 190 
 191 
 192         }
 193         prevtime = currtime / delay;
 194     }
 195     return sanity;
 196 }
 197 
 198 
 199 double hpctimer_wtime(void)
 200 {
 201     return hpctimer_wtime_func_ptr();
 202 }
 203 
 204 
 205 static double hpctimer_wtime_gettimeofday(void)
 206 {
 207     struct timeval tv;
 208     gettimeofday(&tv, NULL);
 209     return (double)tv.tv_sec + 1E-6 * tv.tv_usec;
 210 }
 211 
 212 
 213 
 214 
 215 static double hpctimer_wtime_tsc(void)
 216 {
 217     return (double)(hpctimer_gettsc() - hpctimer_overhead) / (double)hpctimer_freq;
 218 }
 219 
 220 
 221 
 222 
 223 
 224 
 225 
 226 static int hpctimer_tsc_initialize(void)
 227 {
 228     hpctimer_overhead = hpctimer_measure_overhead();
 229     hpctimer_freq = hpctimer_calibrate_sleep(hpctimer_overhead);
 230     return HPCTIMER_SUCCESS;
 231 }
 232 
 233 
 234 
 235 
 236 static __inline__ uint64_t hpctimer_gettsc(void)
 237 {
 238 #if defined(__x86_64__)
 239     uint32_t low, high;
 240     __asm__ __volatile__(
 241         "xorl %%eax, %%eax\n"
 242         "cpuid\n"
 243         ::: "%rax", "%rbx", "%rcx", "%rdx"
 244     );
 245     __asm__ __volatile__(
 246         "rdtsc\n"
 247         : "=a" (low), "=d" (high)
 248     );
 249     return ((uint64_t)high << 32) | low;
 250 
 251 #elif defined(__i386__)
 252     uint64_t tsc;
 253     __asm__ __volatile__(
 254         "xorl %%eax, %%eax\n"
 255         "cpuid\n"
 256         ::: "%eax", "%ebx", "%ecx", "%edx"
 257     );
 258     __asm__ __volatile__(
 259         "rdtsc\n"
 260         : "=A" (tsc)
 261     );
 262     return tsc;
 263 #else
 264 #   error "Unsupported platform"
 265 #endif
 266 }
 267 
 268 
 269 static uint64_t hpctimer_measure_overhead(void)
 270 {
 271     enum {
 272         TSC_OVERHEAD_NTESTS = 10
 273     };
 274     int i;
 275     uint64_t count, overhead = (uint64_t)~0x01;
 276 
 277     
 278     for (i = 0; i < TSC_OVERHEAD_NTESTS; i++) {
 279         count = hpctimer_gettsc();
 280         count = hpctimer_gettsc() - count;
 281         if (count < overhead) {
 282             overhead = count;
 283         }
 284     }
 285     return overhead;
 286 }
 287 
 288 
 289 
 290 
 291 
 292 
 293 
 294 
 295 
 296 
 297 
 298 
 299 
 300 
 301 
 302 
 303 
 304 
 305 
 306 
 307 
 308 
 309 
 310 
 311 
 312 
 313 
 314 
 315 
 316 
 317 
 318 
 319 
 320 static uint64_t hpctimer_calibrate_sleep(uint64_t overhead)
 321 {
 322     uint64_t count;
 323     int delay = 3;
 324 
 325     count = hpctimer_gettsc();
 326     sleep(delay);
 327     count = hpctimer_gettsc() - count - overhead;
 328     return count / delay;
 329 }
 330 
 331 
 332 
 333 
 334 
 335 
 336 
 337 
 338 
 339 
 340 
 341 
 342 
 343 
 344 
 345 
 346 
 347 
 348 
 349 
 350 
 351 
 352 
 353 
 354 
 355 
 356 
 357 
 358 
 359 
 360 
 361