Browse Source

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.
pre-master-46
dwarning 1 year ago
committed by Holger Vogt
parent
commit
3faed1647a
  1. 8
      configure.ac
  2. 61
      src/frontend/resource.c
  3. 14
      src/include/ngspice/ngspice.h
  4. 135
      src/misc/misc_time.c
  5. 19
      src/misc/misc_time.h
  6. 46
      src/sharedspice.c
  7. 14
      src/winmain.c
  8. 3
      visualc/src/include/ngspice/config.h

8
configure.ac

@ -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: # Check time and resources headers and functions:
AC_STRUCT_TM AC_STRUCT_TM
AC_STRUCT_TIMEZONE 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 if test "x$enable_openmp" = xno; then
AC_CHECK_FUNCS([time getrusage])
AC_CHECK_FUNCS([times getrusage])
fi fi
AC_CHECK_FUNCS([utimes]) AC_CHECK_FUNCS([utimes])
AC_CHECK_FUNCS([getrlimit ulimit], [break]) AC_CHECK_FUNCS([getrlimit ulimit], [break])

61
src/frontend/resource.c

@ -77,19 +77,13 @@ init_rlimits(void)
ft_ckspace(); ft_ckspace();
} }
PerfTimer timer;
void void
init_time(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")) { if (!name || eq(name, "totalcputime") || eq(name, "cputime")) {
int total_sec, total_msec; 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)
perf_timer_stop(&timer);
perf_timer_elapsed_sec_ms(&timer, &total_sec, &total_msec);
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;
#ifdef USE_OMP
cpu_elapsed = "elapsed";
#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"; 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;
#elif defined(HAVE_GETRUSAGE)
cpu_elapsed = "CPU"; cpu_elapsed = "CPU";
# else
# ifdef HAVE_FTIME
struct timeb timenow;
ftime(&timenow);
timediff(&timenow, &timebegin, &total_sec, &total_msec);
#elif defined(HAVE_FTIME)
cpu_elapsed = "elapsed"; cpu_elapsed = "elapsed";
# else
# define NO_RUDATA
# endif
# endif
# endif
#endif
#else
# define NO_RUDATA
#endif
#ifndef NO_RUDATA #ifndef NO_RUDATA

14
src/include/ngspice/ngspice.h

@ -117,15 +117,17 @@
# include <sys/time.h> # include <sys/time.h>
# include <sys/resource.h> # include <sys/resource.h>
# endif # endif
#else
# ifdef HAVE_TIMES
#endif
#ifdef HAVE_TIMES
# include <sys/times.h> # include <sys/times.h>
# include <sys/param.h> # include <sys/param.h>
# else
# ifdef HAVE_FTIME
#endif
#ifdef HAVE_GETTIMEOFDAY
# include <sys/time.h>
#endif
#ifdef HAVE_FTIME
# include <sys/timeb.h> # include <sys/timeb.h>
# endif
# endif
#endif #endif
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H

135
src/misc/misc_time.c

@ -8,34 +8,27 @@ Copyright 1990 Regents of the University of California. All rights reserved.
#include "ngspice/ngspice.h" #include "ngspice/ngspice.h"
#include <string.h> #include <string.h>
#include "misc_time.h"
#ifdef HAVE_LOCALTIME
#include <time.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
#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 #endif
#ifdef HAVE_FTIME
# include <sys/timeb.h>
#endif
#include "misc_time.h"
#ifdef USE_OMP
#include <omp.h>
#endif
/* Return the date. Return value is static data. */ /* Return the date. Return value is static data. */
@ -68,15 +61,13 @@ datestring(void)
/* return time interval in seconds and milliseconds */ /* return time interval in seconds and milliseconds */
#ifdef HAVE_FTIME
struct timeb timebegin;
PerfTime 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) { if (*msec < 0) {
*msec += 1000; *msec += 1000;
(*sec)--; (*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. * How many seconds have elapsed in running time.
* This is the routine called in IFseconds * This is the routine called in IFseconds
@ -95,39 +84,65 @@ void timediff(struct timeb *now, struct timeb *begin, int *sec, int *msec)
double double
seconds(void) 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 #else
#ifdef HAVE_TIMES
struct tms tmsbuf;
#error "No timer function available."
#endif
}
times(&tmsbuf);
return((double) tmsbuf.tms_utime / HZ);
void perf_timer_start(PerfTimer *timer)
{
timer->start = seconds();
}
#else
#ifdef HAVE_FTIME
struct timeb timenow;
int sec, msec;
void perf_timer_stop(PerfTimer *timer)
{
timer->end = seconds();
}
ftime(&timenow);
timediff(&timenow, &timebegin, &sec, &msec);
return(sec + (double) msec / 1000.0);
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);
}
#else /* unknown */
/* don't know how to do this in general. */
return(-1.0); /* Obvious error condition */
void perf_timer_get_time(PerfTime *time)
{
double secs = seconds();
time->seconds = (int)secs;
time->milliseconds = (int)((secs - time->seconds) * 1000.0);
#endif /* !FTIME */
#endif /* !SYSV */
#endif /* !BSD */
} }

19
src/misc/misc_time.h

@ -9,12 +9,23 @@
char * datestring(void); char * datestring(void);
double seconds(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 *);
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 *);
#endif
extern PerfTime timebegin;
void timediff(PerfTime *, PerfTime *, int *, int *);
#endif #endif

46
src/sharedspice.c

@ -155,10 +155,6 @@ static bool cont_condition;
#include "ngspice/stringskip.h" #include "ngspice/stringskip.h"
#include "frontend/variable.h" #include "frontend/variable.h"
#ifdef HAVE_FTIME
#include <sys/timeb.h>
#endif
/* To interupt a spice run */ /* To interupt a spice run */
#include <signal.h> #include <signal.h>
typedef void (*sighandler)(int); typedef void (*sighandler)(int);
@ -1908,26 +1904,32 @@ void SetAnalyse(
static unsigned int ng_id1 = 0, ng_id2 = 0; static unsigned int ng_id1 = 0, ng_id2 = 0;
bool thread1; 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 diffsec, diffmillisec; /* differences actual minus prev. time stamp */
int result; /* return value from callback function */ int result; /* return value from callback function */
char* s; /* outputs to callback function */ char* s; /* outputs to callback function */
int OldPercent; /* Previous progress value */ int OldPercent; /* Previous progress value */
char OldAn[128]; /* Previous analysis type */ char OldAn[128]; /* Previous analysis type */
char olds[128]; /* previous output */ char olds[128]; /* previous output */
static struct timeb timebefore; /* previous time stamp */
static PerfTime timebefore; /* previous time stamp */
/* thread 1 */ /* thread 1 */
static int OldPercent1 = -2; /* Previous progress value */ static int OldPercent1 = -2; /* Previous progress value */
static char OldAn1[128]; /* Previous analysis type */ static char OldAn1[128]; /* Previous analysis type */
static char olds1[128]; /* previous output */ static char olds1[128]; /* previous output */
static struct timeb timebefore1; /* previous time stamp */
static PerfTime timebefore1; /* previous time stamp */
/* thread2 */ /* thread2 */
static int OldPercent2 = -2; /* Previous progress value */ static int OldPercent2 = -2; /* Previous progress value */
static char OldAn2[128]; /* Previous analysis type */ static char OldAn2[128]; /* Previous analysis type */
static char olds2[128]; /* previous output */ static char olds2[128]; /* previous output */
static struct timeb timebefore2; /* previous time stamp */
static PerfTime timebefore2; /* previous time stamp */
/*set the two thread ids */ /*set the two thread ids */
unsigned int ng_idl = threadid_self(); unsigned int ng_idl = threadid_self();
@ -1945,20 +1947,16 @@ void SetAnalyse(
strcpy(OldAn, OldAn1); strcpy(OldAn, OldAn1);
strcpy(olds, olds1); strcpy(olds, olds1);
OldPercent = OldPercent1; 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) { else if (ng_idl == ng_id2) {
thread1 = FALSE; thread1 = FALSE;
strcpy(OldAn, OldAn2); strcpy(OldAn, OldAn2);
strcpy(olds, olds2); strcpy(olds, olds2);
OldPercent = OldPercent2; 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 else
return; return;
@ -1972,7 +1970,7 @@ void SetAnalyse(
return; return;
/* get actual time */ /* get actual time */
ftime(&timenow);
perf_timer_get_time(&timenow);
timediff(&timenow, &timebefore, &diffsec, &diffmillisec); timediff(&timenow, &timebefore, &diffsec, &diffmillisec);
s = TMALLOC(char, 128); s = TMALLOC(char, 128);
@ -2023,16 +2021,12 @@ void SetAnalyse(
sprintf( s, "%s: %3.1f%%", Analyse, (double)DecaPercent/10.); sprintf( s, "%s: %3.1f%%", Analyse, (double)DecaPercent/10.);
} }
if (thread1) { 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 { 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 */ /* info when previous analysis period has finished */
if (strcmp(OldAn, Analyse)) { if (strcmp(OldAn, Analyse)) {

14
src/winmain.c

@ -38,7 +38,7 @@
#include "hist_info.h" /* history management */ #include "hist_info.h" /* history management */
#include "ngspice/bool.h" /* bool defined as unsigned char */ #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 "ngspice/memory.h" /* TMALLOC */
#include "winmain.h" #include "winmain.h"
@ -220,8 +220,8 @@ SetAnalyse(char *Analyse, /* in: analysis type */
static int OldPercent = -2; /* Previous progress value */ static int OldPercent = -2; /* Previous progress value */
static char OldAn[128]; /* Previous analysis type */ static char OldAn[128]; /* Previous analysis type */
char s[128], t[128]; /* outputs to analysis window and task bar */ 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 */ int diffsec, diffmillisec; /* differences actual minus prev. time stamp */
WaitForIdle(); WaitForIdle();
@ -232,7 +232,7 @@ SetAnalyse(char *Analyse, /* in: analysis type */
return; return;
/* get actual time */ /* get actual time */
ftime(&timenow);
perf_timer_get_time(&timenow);
timediff(&timenow, &timebefore, &diffsec, &diffmillisec); timediff(&timenow, &timebefore, &diffsec, &diffmillisec);
OldPercent = DecaPercent; OldPercent = DecaPercent;
@ -255,10 +255,8 @@ SetAnalyse(char *Analyse, /* in: analysis type */
sprintf(s, " %s: %3.1f%%", Analyse, (double)DecaPercent/10.); sprintf(s, " %s: %3.1f%%", Analyse, (double)DecaPercent/10.);
sprintf(t, "%s %3.1f%%", PACKAGE_STRING, (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 */ /* info when previous analysis period has finished */
if (strcmp(OldAn, Analyse)) { if (strcmp(OldAn, Analyse)) {
if ((ft_nginfo || ft_ngdebug) && (strcmp(OldAn, ""))) if ((ft_nginfo || ft_ngdebug) && (strcmp(OldAn, "")))

3
visualc/src/include/ngspice/config.h

@ -163,6 +163,9 @@
/* Define to 1 if you have the `fork' function. */ /* Define to 1 if you have the `fork' function. */
/* #undef HAVE_FORK */ /* #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 to 1 if you have the `ftime' function. */
#define HAVE_FTIME 1 #define HAVE_FTIME 1

Loading…
Cancel
Save