Reorder and renovate timer functions taking into account ngspice multiprocessor capabilities
by using available high performance functions first. Deprecated ftime() still acts as a backup function. Solution is portable for today's operating systems and compilers.
This commit is contained in:
parent
a42ea98471
commit
3faed1647a
|
|
@ -906,12 +906,12 @@ AC_CHECK_HEADERS([arpa/inet.h netdb.h netinet/in.h stddef.h sys/file.h sys/param
|
|||
# Check time and resources headers and functions:
|
||||
AC_STRUCT_TM
|
||||
AC_STRUCT_TIMEZONE
|
||||
AC_CHECK_FUNCS([localtime])
|
||||
AC_CHECK_FUNCS([time localtime])
|
||||
|
||||
AC_CHECK_FUNCS([ftime gettimeofday])
|
||||
# Do not use time or getrusage function for CPU time measurement under OpenMP
|
||||
AC_CHECK_FUNCS([queryperformancecounter clock_gettime gettimeofday ftime])
|
||||
# Do not use times or getrusage function for CPU time measurement under OpenMP
|
||||
if test "x$enable_openmp" = xno; then
|
||||
AC_CHECK_FUNCS([time getrusage])
|
||||
AC_CHECK_FUNCS([times getrusage])
|
||||
fi
|
||||
AC_CHECK_FUNCS([utimes])
|
||||
AC_CHECK_FUNCS([getrlimit ulimit], [break])
|
||||
|
|
|
|||
|
|
@ -77,19 +77,13 @@ init_rlimits(void)
|
|||
ft_ckspace();
|
||||
}
|
||||
|
||||
PerfTimer timer;
|
||||
|
||||
void
|
||||
init_time(void)
|
||||
{
|
||||
#ifdef HAVE_GETRUSAGE
|
||||
#else
|
||||
# ifdef HAVE_TIMES
|
||||
# else
|
||||
# ifdef HAVE_FTIME
|
||||
ftime(&timebegin);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
perf_timer_get_time(&timebegin);
|
||||
perf_timer_start(&timer);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -169,38 +163,33 @@ printres(char *name)
|
|||
if (!name || eq(name, "totalcputime") || eq(name, "cputime")) {
|
||||
int total_sec, total_msec;
|
||||
|
||||
# ifdef HAVE_GETRUSAGE
|
||||
int ret;
|
||||
struct rusage ruse;
|
||||
memset(&ruse, 0, sizeof(ruse));
|
||||
ret = getrusage(RUSAGE_SELF, &ruse);
|
||||
if (ret == -1)
|
||||
perror("getrusage(): ");
|
||||
#if defined (USE_OMP) \
|
||||
|| defined (HAVE_QUERYPERFORMANCECOUNTER) || defined(HAVE_CLOCK_GETTIME) \
|
||||
|| defined (HAVE_GETTIMEOFDAY) || defined(HAVE_TIMES) \
|
||||
|| defined (HAVE_GETRUSAGE) || defined(HAVE_FTIME)
|
||||
|
||||
total_sec = (int) (ruse.ru_utime.tv_sec + ruse.ru_stime.tv_sec);
|
||||
total_msec = (int) (ruse.ru_utime.tv_usec + ruse.ru_stime.tv_usec) / 1000;
|
||||
cpu_elapsed = "CPU";
|
||||
# else
|
||||
# ifdef HAVE_TIMES
|
||||
struct tms ruse;
|
||||
times(&ruse);
|
||||
clock_t x = ruse.tms_utime + ruse.tms_stime;
|
||||
clock_t hz = (clock_t) sysconf(_SC_CLK_TCK);
|
||||
total_sec = x / hz;
|
||||
total_msec = ((x % hz) * 1000) / hz;
|
||||
cpu_elapsed = "CPU";
|
||||
# else
|
||||
# ifdef HAVE_FTIME
|
||||
struct timeb timenow;
|
||||
ftime(&timenow);
|
||||
timediff(&timenow, &timebegin, &total_sec, &total_msec);
|
||||
perf_timer_stop(&timer);
|
||||
perf_timer_elapsed_sec_ms(&timer, &total_sec, &total_msec);
|
||||
|
||||
#ifdef USE_OMP
|
||||
cpu_elapsed = "elapsed";
|
||||
# else
|
||||
# define NO_RUDATA
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#elif defined(HAVE_QUERYPERFORMANCECOUNTER)
|
||||
cpu_elapsed = "elapsed";
|
||||
#elif defined(HAVE_CLOCK_GETTIME)
|
||||
cpu_elapsed = "elapsed";
|
||||
#elif defined(HAVE_GETTIMEOFDAY)
|
||||
cpu_elapsed = "elapsed";
|
||||
#elif defined(HAVE_TIMES)
|
||||
cpu_elapsed = "CPU";
|
||||
#elif defined(HAVE_GETRUSAGE)
|
||||
cpu_elapsed = "CPU";
|
||||
#elif defined(HAVE_FTIME)
|
||||
cpu_elapsed = "elapsed";
|
||||
#endif
|
||||
|
||||
#else
|
||||
# define NO_RUDATA
|
||||
#endif
|
||||
|
||||
#ifndef NO_RUDATA
|
||||
|
||||
|
|
|
|||
|
|
@ -117,15 +117,17 @@
|
|||
# include <sys/time.h>
|
||||
# include <sys/resource.h>
|
||||
# endif
|
||||
#else
|
||||
# ifdef HAVE_TIMES
|
||||
# include <sys/times.h>
|
||||
# include <sys/param.h>
|
||||
# else
|
||||
# ifdef HAVE_FTIME
|
||||
# include <sys/timeb.h>
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TIMES
|
||||
# include <sys/times.h>
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
#ifdef HAVE_GETTIMEOFDAY
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
#ifdef HAVE_FTIME
|
||||
# include <sys/timeb.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
|
|
|
|||
|
|
@ -8,35 +8,28 @@ Copyright 1990 Regents of the University of California. All rights reserved.
|
|||
|
||||
#include "ngspice/ngspice.h"
|
||||
#include <string.h>
|
||||
|
||||
#if defined(HAS_WINGUI) || defined(__MINGW32__) || defined(_MSC_VER)
|
||||
#ifdef HAVE_QUERYPERFORMANCECOUNTER
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
/*
|
||||
* The ngspice.h file included above defines BOOLEAN (via bool.h) and this
|
||||
* clashes with the definition obtained from windows.h (via winnt.h).
|
||||
* However, BOOLEAN is not used by this file so we can work round this problem
|
||||
* by undefining BOOLEAN before including windows.h
|
||||
* SJB - April 2005
|
||||
*/
|
||||
#undef BOOLEAN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "misc_time.h"
|
||||
|
||||
#ifdef HAVE_LOCALTIME
|
||||
#include <time.h>
|
||||
#ifdef USE_OMP
|
||||
#include <omp.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GETRUSAGE
|
||||
# include <sys/types.h>
|
||||
# include <sys/time.h>
|
||||
# include <sys/resource.h>
|
||||
#else
|
||||
# ifdef HAVE_TIMES
|
||||
# include <sys/types.h>
|
||||
# include <sys/times.h>
|
||||
# include <sys/param.h>
|
||||
# else
|
||||
# ifdef HAVE_FTIME
|
||||
/* default to ftime if we can't get real CPU times */
|
||||
# include <sys/types.h>
|
||||
# include <sys/timeb.h>
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FTIME
|
||||
# include <sys/timeb.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* Return the date. Return value is static data. */
|
||||
|
||||
char *
|
||||
|
|
@ -68,15 +61,13 @@ datestring(void)
|
|||
|
||||
/* return time interval in seconds and milliseconds */
|
||||
|
||||
#ifdef HAVE_FTIME
|
||||
PerfTime timebegin;
|
||||
|
||||
struct timeb timebegin;
|
||||
|
||||
void timediff(struct timeb *now, struct timeb *begin, int *sec, int *msec)
|
||||
void timediff(PerfTime *now, PerfTime *begin, int *sec, int *msec)
|
||||
{
|
||||
|
||||
*msec = (int) now->millitm - (int) begin->millitm;
|
||||
*sec = (int) now->time - (int) begin->time;
|
||||
*msec = (int) now->milliseconds - (int) begin->milliseconds;
|
||||
*sec = (int) now->seconds - (int) begin->seconds;
|
||||
if (*msec < 0) {
|
||||
*msec += 1000;
|
||||
(*sec)--;
|
||||
|
|
@ -85,8 +76,6 @@ void timediff(struct timeb *now, struct timeb *begin, int *sec, int *msec)
|
|||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* How many seconds have elapsed in running time.
|
||||
* This is the routine called in IFseconds
|
||||
|
|
@ -95,39 +84,65 @@ void timediff(struct timeb *now, struct timeb *begin, int *sec, int *msec)
|
|||
double
|
||||
seconds(void)
|
||||
{
|
||||
#ifdef HAVE_GETRUSAGE
|
||||
int ret;
|
||||
struct rusage ruse;
|
||||
|
||||
memset(&ruse, 0, sizeof(ruse));
|
||||
ret = getrusage(RUSAGE_SELF, &ruse);
|
||||
if(ret == -1) {
|
||||
perror("getrusage(): ");
|
||||
return 1;
|
||||
}
|
||||
return ((double)ruse.ru_utime.tv_sec + (double) ruse.ru_utime.tv_usec / 1000000.0);
|
||||
#ifdef USE_OMP
|
||||
// Usage of OpenMP time function
|
||||
return omp_get_wtime();
|
||||
#elif defined(HAVE_QUERYPERFORMANCECOUNTER)
|
||||
// Windows (MSC and mingw) specific implementation
|
||||
LARGE_INTEGER frequency, counter;
|
||||
QueryPerformanceFrequency(&frequency);
|
||||
QueryPerformanceCounter(&counter);
|
||||
return (double)counter.QuadPart / frequency.QuadPart;
|
||||
#elif defined(HAVE_CLOCK_GETTIME)
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return ts.tv_sec + ts.tv_nsec / 1e9;
|
||||
#elif defined(HAVE_GETTIMEOFDAY)
|
||||
// Usage of gettimeofday
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return tv.tv_sec + tv.tv_usec / 1e6;
|
||||
#elif defined(HAVE_TIMES)
|
||||
// Usage of times
|
||||
struct tms t;
|
||||
clock_t ticks = times(&t);
|
||||
return (double)ticks / sysconf(_SC_CLK_TCK);
|
||||
#elif defined(HAVE_GETRUSAGE)
|
||||
// Usage of getrusage
|
||||
struct rusage usage;
|
||||
getrusage(RUSAGE_SELF, &usage);
|
||||
return usage.ru_utime.tv_sec + usage.ru_utime.tv_usec / 1e6;
|
||||
#elif defined(HAVE_FTIME)
|
||||
// Usage of ftime
|
||||
struct timeb tb;
|
||||
ftime(&tb);
|
||||
return tb.time + tb.millitm / 1000.0;
|
||||
#else
|
||||
#ifdef HAVE_TIMES
|
||||
|
||||
struct tms tmsbuf;
|
||||
|
||||
times(&tmsbuf);
|
||||
return((double) tmsbuf.tms_utime / HZ);
|
||||
|
||||
#else
|
||||
#ifdef HAVE_FTIME
|
||||
struct timeb timenow;
|
||||
int sec, msec;
|
||||
|
||||
ftime(&timenow);
|
||||
timediff(&timenow, &timebegin, &sec, &msec);
|
||||
return(sec + (double) msec / 1000.0);
|
||||
|
||||
#else /* unknown */
|
||||
/* don't know how to do this in general. */
|
||||
return(-1.0); /* Obvious error condition */
|
||||
|
||||
#endif /* !FTIME */
|
||||
#endif /* !SYSV */
|
||||
#endif /* !BSD */
|
||||
#error "No timer function available."
|
||||
#endif
|
||||
}
|
||||
|
||||
void perf_timer_start(PerfTimer *timer)
|
||||
{
|
||||
timer->start = seconds();
|
||||
}
|
||||
|
||||
void perf_timer_stop(PerfTimer *timer)
|
||||
{
|
||||
timer->end = seconds();
|
||||
}
|
||||
|
||||
void perf_timer_elapsed_sec_ms(const PerfTimer *timer, int *seconds, int *milliseconds)
|
||||
{
|
||||
double elapsed = timer->end - timer->start;
|
||||
*seconds = (int)elapsed;
|
||||
*milliseconds = (int)((elapsed - *seconds) * 1000.0);
|
||||
}
|
||||
|
||||
void perf_timer_get_time(PerfTime *time)
|
||||
{
|
||||
double secs = seconds();
|
||||
time->seconds = (int)secs;
|
||||
time->milliseconds = (int)((secs - time->seconds) * 1000.0);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,12 +9,23 @@
|
|||
char * datestring(void);
|
||||
double seconds(void);
|
||||
|
||||
#ifdef HAVE_FTIME
|
||||
typedef struct {
|
||||
double start;
|
||||
double end;
|
||||
} PerfTimer;
|
||||
|
||||
extern struct timeb timebegin;
|
||||
typedef struct {
|
||||
int seconds;
|
||||
int milliseconds;
|
||||
} PerfTime;
|
||||
|
||||
void timediff(struct timeb *, struct timeb *, int *, int *);
|
||||
|
||||
#endif
|
||||
void perf_timer_start(PerfTimer *);
|
||||
void perf_timer_stop(PerfTimer *);
|
||||
void perf_timer_elapsed_sec_ms(const PerfTimer *, int *, int *);
|
||||
void perf_timer_get_time(PerfTime *);
|
||||
|
||||
extern PerfTime timebegin;
|
||||
|
||||
void timediff(PerfTime *, PerfTime *, int *, int *);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -155,10 +155,6 @@ static bool cont_condition;
|
|||
#include "ngspice/stringskip.h"
|
||||
#include "frontend/variable.h"
|
||||
|
||||
#ifdef HAVE_FTIME
|
||||
#include <sys/timeb.h>
|
||||
#endif
|
||||
|
||||
/* To interupt a spice run */
|
||||
#include <signal.h>
|
||||
typedef void (*sighandler)(int);
|
||||
|
|
@ -1908,26 +1904,32 @@ void SetAnalyse(
|
|||
static unsigned int ng_id1 = 0, ng_id2 = 0;
|
||||
bool thread1;
|
||||
|
||||
#ifdef HAVE_FTIME
|
||||
struct timeb timenow; /* actual time stamp */
|
||||
#if defined (USE_OMP) \
|
||||
|| defined (HAVE_QUERYPERFORMANCECOUNTER) \
|
||||
|| defined (HAVE_CLOCK_GETTIME) \
|
||||
|| defined (HAVE_GETTIMEOFDAY) \
|
||||
|| defined (HAVE_TIMES) \
|
||||
|| defined (HAVE_GETRUSAGE) \
|
||||
|| defined (HAVE_FTIME)
|
||||
PerfTime timenow; /* actual time stamp */
|
||||
int diffsec, diffmillisec; /* differences actual minus prev. time stamp */
|
||||
int result; /* return value from callback function */
|
||||
char* s; /* outputs to callback function */
|
||||
int OldPercent; /* Previous progress value */
|
||||
char OldAn[128]; /* Previous analysis type */
|
||||
char olds[128]; /* previous output */
|
||||
static struct timeb timebefore; /* previous time stamp */
|
||||
static PerfTime timebefore; /* previous time stamp */
|
||||
|
||||
/* thread 1 */
|
||||
static int OldPercent1 = -2; /* Previous progress value */
|
||||
static char OldAn1[128]; /* Previous analysis type */
|
||||
static char olds1[128]; /* previous output */
|
||||
static struct timeb timebefore1; /* previous time stamp */
|
||||
static PerfTime timebefore1; /* previous time stamp */
|
||||
/* thread2 */
|
||||
static int OldPercent2 = -2; /* Previous progress value */
|
||||
static char OldAn2[128]; /* Previous analysis type */
|
||||
static char olds2[128]; /* previous output */
|
||||
static struct timeb timebefore2; /* previous time stamp */
|
||||
static PerfTime timebefore2; /* previous time stamp */
|
||||
|
||||
/*set the two thread ids */
|
||||
unsigned int ng_idl = threadid_self();
|
||||
|
|
@ -1945,20 +1947,16 @@ void SetAnalyse(
|
|||
strcpy(OldAn, OldAn1);
|
||||
strcpy(olds, olds1);
|
||||
OldPercent = OldPercent1;
|
||||
timebefore.dstflag = timebefore1.dstflag;
|
||||
timebefore.millitm = timebefore1.millitm;
|
||||
timebefore.time = timebefore1.time;
|
||||
timebefore.timezone = timebefore1.timezone;
|
||||
timebefore.milliseconds = timebefore1.milliseconds;
|
||||
timebefore.seconds = timebefore1.seconds;
|
||||
}
|
||||
else if (ng_idl == ng_id2) {
|
||||
thread1 = FALSE;
|
||||
strcpy(OldAn, OldAn2);
|
||||
strcpy(olds, olds2);
|
||||
OldPercent = OldPercent2;
|
||||
timebefore.dstflag = timebefore2.dstflag;
|
||||
timebefore.millitm = timebefore2.millitm;
|
||||
timebefore.time = timebefore2.time;
|
||||
timebefore.timezone = timebefore2.timezone;
|
||||
timebefore.milliseconds = timebefore2.milliseconds;
|
||||
timebefore.seconds = timebefore2.seconds;
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
|
@ -1972,7 +1970,7 @@ void SetAnalyse(
|
|||
return;
|
||||
|
||||
/* get actual time */
|
||||
ftime(&timenow);
|
||||
perf_timer_get_time(&timenow);
|
||||
timediff(&timenow, &timebefore, &diffsec, &diffmillisec);
|
||||
s = TMALLOC(char, 128);
|
||||
|
||||
|
|
@ -2023,16 +2021,12 @@ void SetAnalyse(
|
|||
sprintf( s, "%s: %3.1f%%", Analyse, (double)DecaPercent/10.);
|
||||
}
|
||||
if (thread1) {
|
||||
timebefore1.dstflag = timenow.dstflag;
|
||||
timebefore1.millitm = timenow.millitm;
|
||||
timebefore1.time = timenow.time;
|
||||
timebefore1.timezone = timenow.timezone;
|
||||
timebefore1.milliseconds = timenow.milliseconds;
|
||||
timebefore1.seconds = timenow.seconds;
|
||||
}
|
||||
else {
|
||||
timebefore2.dstflag = timenow.dstflag;
|
||||
timebefore2.millitm = timenow.millitm;
|
||||
timebefore2.time = timenow.time;
|
||||
timebefore2.timezone = timenow.timezone;
|
||||
timebefore2.milliseconds = timenow.milliseconds;
|
||||
timebefore2.seconds = timenow.seconds;
|
||||
}
|
||||
/* info when previous analysis period has finished */
|
||||
if (strcmp(OldAn, Analyse)) {
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
#include "hist_info.h" /* history management */
|
||||
#include "ngspice/bool.h" /* bool defined as unsigned char */
|
||||
#include "misc/misc_time.h" /* timediff */
|
||||
#include "misc/misc_time.h" /* timer functions and structure */
|
||||
#include "ngspice/memory.h" /* TMALLOC */
|
||||
#include "winmain.h"
|
||||
|
||||
|
|
@ -220,8 +220,8 @@ SetAnalyse(char *Analyse, /* in: analysis type */
|
|||
static int OldPercent = -2; /* Previous progress value */
|
||||
static char OldAn[128]; /* Previous analysis type */
|
||||
char s[128], t[128]; /* outputs to analysis window and task bar */
|
||||
static struct timeb timebefore; /* previous time stamp */
|
||||
struct timeb timenow; /* actual time stamp */
|
||||
static PerfTime timebefore; /* previous time stamp */
|
||||
PerfTime timenow; /* actual time stamp */
|
||||
int diffsec, diffmillisec; /* differences actual minus prev. time stamp */
|
||||
|
||||
WaitForIdle();
|
||||
|
|
@ -232,7 +232,7 @@ SetAnalyse(char *Analyse, /* in: analysis type */
|
|||
return;
|
||||
|
||||
/* get actual time */
|
||||
ftime(&timenow);
|
||||
perf_timer_get_time(&timenow);
|
||||
timediff(&timenow, &timebefore, &diffsec, &diffmillisec);
|
||||
|
||||
OldPercent = DecaPercent;
|
||||
|
|
@ -255,10 +255,8 @@ SetAnalyse(char *Analyse, /* in: analysis type */
|
|||
sprintf(s, " %s: %3.1f%%", Analyse, (double)DecaPercent/10.);
|
||||
sprintf(t, "%s %3.1f%%", PACKAGE_STRING, (double)DecaPercent/10.);
|
||||
}
|
||||
timebefore.dstflag = timenow.dstflag;
|
||||
timebefore.millitm = timenow.millitm;
|
||||
timebefore.time = timenow.time;
|
||||
timebefore.timezone = timenow.timezone;
|
||||
timebefore.milliseconds = timenow.milliseconds;
|
||||
timebefore.seconds = timenow.seconds;
|
||||
/* info when previous analysis period has finished */
|
||||
if (strcmp(OldAn, Analyse)) {
|
||||
if ((ft_nginfo || ft_ngdebug) && (strcmp(OldAn, "")))
|
||||
|
|
|
|||
|
|
@ -163,6 +163,9 @@
|
|||
/* Define to 1 if you have the `fork' function. */
|
||||
/* #undef HAVE_FORK */
|
||||
|
||||
/* Define to 1 if you have the `queryperformancecounter' function. */
|
||||
#define HAVE_QUERYPERFORMANCECOUNTER 1
|
||||
|
||||
/* Define to 1 if you have the `ftime' function. */
|
||||
#define HAVE_FTIME 1
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue