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
|
/*********************************************************************
* Copyright 2020, UCAR/Unidata
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
*********************************************************************/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#ifdef HAVE_TIME_H
#include <time.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#ifdef _WIN32
#include <windows.h>
#endif
#include "timer_utils.h"
#undef DEBUG
static int NCT_initialized = 0;
#ifdef _WIN32
LARGE_INTEGER frequency;
LARGE_INTEGER starttime;
void
NCT_inittimer(void)
{
if(NCT_initialized) return;
#ifdef DEBUG
fprintf(stderr,"timer mechanism: QueryPerformanceCounter\n");
#endif
LARGE_INTEGER li;
(void)QueryPerformanceFrequency(&frequency);
QueryPerformanceCounter(&starttime);
#ifdef DEBUG
fprintf(stderr,"frequency=%lld starttime=%lld\n",frequency.QuadPart,starttime.QuadPart);
#endif
NCT_initialized = 1;
}
#else
void
NCT_inittimer(void)
{
if(NCT_initialized) return;
#ifdef DEBUG
#if defined HAVE_CLOCK_GETTIME
fprintf(stderr,"timer mechanism: clock_gettime\n");
#elif defined HAVE_GETTIMEOFDAY
fprintf(stderr,"timer mechanism: gettimeofday\n");
#elif defined HAVE_GETRUSAGE
fprintf(stderr,"timer mechanism: getrusage\n");
#else
fprintf(stderr,"timer mechanism: Unknown\n");
#endif
#endif /*DEBUG*/
NCT_initialized = 1;
}
#endif
void
NCT_marktime(Nanotime* nt)
{
#ifdef _WIN32
LARGE_INTEGER endtime;
QueryPerformanceCounter(&endtime);
nt->tv_sec = endtime.QuadPart / 1000000000;
nt->tv_nsec = endtime.QuadPart % 1000000000;
#ifdef DEBUG
fprintf(stderr,"endtime=%lld\n",endtime.QuadPart);
#endif
#endif
#ifndef _WIN32
/* Pick one */
#ifdef HAVE_CLOCK_GETTIME
clockid_t clk_id = CLOCK_MONOTONIC;
struct timespec t;
clock_gettime(clk_id,&t);
nt->tv_sec = (long long)t.tv_sec;
nt->tv_nsec = (long long)t.tv_nsec;
#elif defined HAVE_GETTIMEOFDAY
struct timeval tp;
gettimeofday(&tp, NULL);
nt->tv_sec = (long long)tp.tv_sec;
nt->tv_nsec = 1000*(long long)tp.tv_usec;
# elif defined HAVE_GETRUSAGE
struct rusage ru;
getrusage(RUSAGE_SELF, &ru);
nt->tv_sec = (long long)(ru.ru_utime.tv_sec + ru.ru_stime.tv_sec);
nt->tv_nsec = (long long)(1000*(ru.ru_utime.tv_usec + ru.ru_stime.tv_usec));
#endif
#endif
}
void
NCT_elapsedtime(Nanotime* nt0, Nanotime* nt1, Nanotime* delta)
{
long long nsec[2];
long long deltansec;
nsec[0] = nt0->tv_nsec+(1000000000 * nt0->tv_sec);
nsec[1] = nt1->tv_nsec+(1000000000 * nt1->tv_sec);
deltansec = nsec[1] - nsec[0];
delta->tv_nsec = deltansec % 1000000000;
delta->tv_sec = deltansec / 1000000000;
#ifdef DEBUG
fprintf(stderr,"delta=(%lld,%lld)\n",delta->tv_sec,delta->tv_nsec);
#endif
}
int
NCT_reporttime(unsigned nelems, Nanotime* times, struct TimeRange range, const char* tag)
{
Nanotime delta;
long long nsec,avg;
double dnsec,dsec,davg;
NCT_elapsedtime(×[0],×[1],&delta);
nsec = NCT_nanoseconds(delta);
avg = nsec / nelems;
#ifdef DEBUG
fprintf(stderr,"nsec=%lld avg=%lld\n",nsec,avg);
#endif
dnsec = (double)nsec;
dsec = dnsec / 1000000000.0;
#ifdef DEBUG
fprintf(stderr,"dsec=%g dnsec=%g\n",dsec,dnsec);
#endif
davg = (dnsec/nelems);
fprintf(stderr,"\t%s:\t%8.6lf sec",tag,dsec);
fprintf(stderr," avg=%5.2lf nsec\n",davg);
#ifdef DEBUG
fprintf(stderr,"range: min=%lld max=%lld\n",range.min,range.max);
#endif
if(!NCT_rangetest(avg,range)) {
fprintf(stderr,"*** WARNING: unexpectedly large timing values%s\n",tag);
}
return 1;
}
long long
NCT_nanoseconds(Nanotime time)
{
return (time.tv_sec * 1000000000) + time.tv_nsec;
}
/* Provide a time range tester */
int
NCT_rangetest(long long nsec, struct TimeRange range)
{
if(nsec < range.min) {
fprintf(stderr,"range: time=%lld < min=%lld\n",nsec,range.min);
return 0;
}
if(nsec > range.max) {
fprintf(stderr,"range: time=%lld > max=%lld\n",nsec,range.max);
return 0;
}
return 1;
}
|