diff --git a/gptl.c b/gptl.c index 4b5e79e0..f0390373 100644 --- a/gptl.c +++ b/gptl.c @@ -33,7 +33,7 @@ typedef struct { static Settings cpustats = {GPTLcpu, "Usr sys usr+sys ", false}; static Settings wallstats = {GPTLwall, "Wallclock max min ", true }; -static Settings overheadstats = {GPTLoverhead, "Overhead ", true }; +static Settings overheadstats = {GPTLoverhead, "Overhead gtod part " , true }; static const int tablesize = 128*MAX_CHARS; /* 128 is size of ASCII char set */ static Hashentry **hashtable; /* table of entries hashed by sum of chars */ @@ -242,7 +242,11 @@ int GPTLstart (const char *name) /* timer name */ if ((t = get_thread_num (&nthreads, &maxthreads)) < 0) return GPTLerror ("GPTLstart\n"); - /* 1st calls to overheadstart and gettimeofday are solely for overhead timing */ + /* + ** 1st calls to overheadstart and gettimeofday are solely for overhead timing + ** Would prefer to start overhead calcs before get_thread_num, but the + ** thread number is required by PAPI counters + */ if (overheadstats.enabled) { #ifdef HAVE_PAPI @@ -789,6 +793,7 @@ static void printstats (const Timer *timer, /* timer to print */ float sys; /* system time */ float usrsys; /* usr + sys */ float elapse; /* elapsed time */ + float gtodportion; /* timer overhead due to gettimeofday only */ if ((ticks_per_sec = sysconf (_SC_CLK_TCK)) == -1) (void) GPTLerror ("printstats: token _SC_CLK_TCK is not defined\n"); @@ -828,16 +833,20 @@ static void printstats (const Timer *timer, /* timer to print */ /* ** Add cost of gettimeofday to overhead est. Factor of 2 is because both - ** start and stop were called. + ** start and stop were called. Second factor of 2 is because gettimeofday + ** was called a total of 4 times for each start/stop pair. */ if (overheadstats.enabled) { - fprintf (fp, "%9.3f ", timer->wall.overhead + timer->count * 2 * gtodoverhead); + gtodportion = timer->count * 2 * gtodoverhead; + fprintf (fp, "%9.3f %9.3f ", + timer->wall.overhead + gtodportion, + 2*gtodportion); } } #ifdef HAVE_PAPI - GPTL_PAPIpr (fp, &timer->aux); + GPTL_PAPIpr (fp, &timer->aux, t, timer->count); #endif fprintf (fp, "\n"); diff --git a/gptl_papi.c b/gptl_papi.c index 053dc1e0..c093d78c 100644 --- a/gptl_papi.c +++ b/gptl_papi.c @@ -137,6 +137,7 @@ static char papiname[PAPI_MAX_STR_LEN]; /* returned from PAPI_event_code_to_nam static const int BADCOUNT = -999999; /* Set counters to this when they are bad */ static int GPTLoverheadindx = -1; /* index into counters array */ static long_long *lastoverhead; /* needed because aux not available for overhead */ +static long_long *readoverhead; /* overhead due solely to reading PAPI counters */ /* Function prototypes */ @@ -230,11 +231,13 @@ int GPTL_PAPIinitialize (const int maxthreads) /* number of threads */ EventSet = (int *) GPTLallocate (maxthreads * sizeof (int)); papicounters = (long_long **) GPTLallocate (maxthreads * sizeof (long_long *)); lastoverhead = (long_long *) GPTLallocate (maxthreads * sizeof (long_long)); + readoverhead = (long_long *) GPTLallocate (maxthreads * sizeof (long_long)); for (t = 0; t < maxthreads; t++) { EventSet[t] = PAPI_NULL; papicounters[t] = (long_long *) GPTLallocate (MAX_AUX * sizeof (long_long)); lastoverhead[t] = -1; + readoverhead[t] = -1; } /* @@ -304,11 +307,13 @@ static int create_and_start_events (const int t) /* thread number */ { int ret; int n; + long_long counters1[MAX_AUX]; /* Temp counter for estimating PAPI_read overhead */ + long_long counters2[MAX_AUX]; /* Temp counter for estimating PAPI_read overhead */ /* Create the event set */ if ((ret = PAPI_create_eventset (&EventSet[t])) != PAPI_OK) - return GPTLerror ("GPTL_PAPIstart: failure creating eventset: %s\n", + return GPTLerror ("create_and_start_events: failure creating eventset: %s\n", PAPI_strerror (ret)); /* Add requested events to the event set */ @@ -316,7 +321,7 @@ static int create_and_start_events (const int t) /* thread number */ for (n = 0; n < nevents; n++) { if ((ret = PAPI_add_event (EventSet[t], eventlist[n].counter)) != PAPI_OK) { printf ("%s\n", PAPI_strerror (ret)); - return GPTLerror ("GPTL_PAPIstart: failure adding event: %s\n", + return GPTLerror ("create_and_start_events: failure adding event: %s\n", eventlist[n].str); } } @@ -326,6 +331,19 @@ static int create_and_start_events (const int t) /* thread number */ if ((ret = PAPI_start (EventSet[t])) != PAPI_OK) return GPTLerror ("%s\n", PAPI_strerror (ret)); + /* Estimate overhead of calling PAPI_read, to be used later in printing */ + + if (GPTLoverheadindx > -1) { + if ((ret = PAPI_read (EventSet[t], counters1)) != PAPI_OK) + return GPTLerror ("create_and_start_events: %s\n", PAPI_strerror (ret)); + if ((ret = PAPI_read (EventSet[t], counters1)) != PAPI_OK) + return GPTLerror ("create_and_start_events: %s\n", PAPI_strerror (ret)); + if ((ret = PAPI_read (EventSet[t], counters2)) != PAPI_OK) + return GPTLerror ("create_and_start_events: %s\n", PAPI_strerror (ret)); + + readoverhead[t] = counters2[GPTLoverheadindx] - counters1[GPTLoverheadindx]; + } + return 0; } @@ -497,8 +515,8 @@ void GPTL_PAPIprstr (FILE *fp) /* file descriptor */ for (n = 0; n < nevents; n++) fprintf (fp, "%16s ", eventlist[n].prstr); - if (lastoverhead[0] > -1) - fprintf (fp, "Overhead (cycles)"); + if (GPTLoverheadindx > -1) + fprintf (fp, "Overhead (cyc) PAPI_read part "); } /* @@ -511,9 +529,13 @@ void GPTL_PAPIprstr (FILE *fp) /* file descriptor */ */ void GPTL_PAPIpr (FILE *fp, /* file descriptor to write to */ - const Papistats *aux) /* stats to write */ + const Papistats *aux, /* stats to write */ + const int t, /* thread number */ + const int count) /* number of invocations */ { int n; + long_long papireadportion; /* overhead due just to PAPI_read */ + long_long overhead ; /* overhead including PAPI_read */ for (n = 0; n < nevents; n++) { if (aux->accum[n] < 1000000) @@ -522,13 +544,19 @@ void GPTL_PAPIpr (FILE *fp, /* file descriptor to write to */ fprintf (fp, "%16.10e ", (double) aux->accum[n]); } - /* The check on lastoverhead > -1 determines whether it was ever set */ + /* Print overhead estimate. The check on lastoverhead > -1 determines + ** whether it was ever set. Note similarity of overhead calc. to + ** gettimeofday calc. in gptl.c. + */ - if (lastoverhead[0] > -1) + if (GPTLoverheadindx > -1) { + papireadportion = count * 2 * readoverhead[t]; + overhead = aux->accum_cycles + papireadportion; if (aux->accum_cycles < 1000000) - fprintf (fp, "%16ld ", (long) aux->accum_cycles); + fprintf (fp, "%16ld %16ld ", (long) overhead, (long) (2*papireadportion)); else - fprintf (fp, "%16.10e ", (double) aux->accum_cycles); + fprintf (fp, "%16.10e %16.10e ", (double) overhead, (double) (2*papireadportion)); + } } /* diff --git a/private.h b/private.h index 4b0c8103..9aa570a7 100644 --- a/private.h +++ b/private.h @@ -1,5 +1,5 @@ /* -$Id: private.h,v 1.22 2005-06-15 05:52:25 rosinski Exp $ +$Id: private.h,v 1.23 2005-06-23 07:18:29 rosinski Exp $ */ #include @@ -16,7 +16,7 @@ #define STRMATCH(X,Y) (strcmp((X),(Y)) == 0) /* longest timer name allowed (probably safe to just change) */ -#define MAX_CHARS 15 +#define MAX_CHARS 31 /* max allowable number of PAPI counters (though most machines allow fewer */ #define MAX_AUX 8 @@ -81,7 +81,7 @@ extern int GPTL_PAPIinitialize (const int); extern int GPTL_PAPIstart (const int, Papistats *); extern int GPTL_PAPIstop (const int, Papistats *); extern void GPTL_PAPIprstr (FILE *); -extern void GPTL_PAPIpr (FILE *, const Papistats *); +extern void GPTL_PAPIpr (FILE *, const Papistats *, const int, const int); extern void GPTL_PAPIadd (Papistats *, const Papistats *); extern int GPTL_PAPIoverheadstart (const int); extern int GPTL_PAPIoverheadstop (const int, Papistats *); diff --git a/tests/overhead.c b/tests/overhead.c index 120035e0..160d0aa5 100644 --- a/tests/overhead.c +++ b/tests/overhead.c @@ -1,9 +1,10 @@ -#include /* gettimeofday */ +#include /* gettimeofday */ #include /* times */ #include #include #include -#include /* gettimeofday */ +#include /* gettimeofday */ +#include #ifdef THREADED_OMP #include @@ -15,8 +16,56 @@ #include "../gptl.h" -static void *getentry (char *, char *, int *); +#define tablesiz 128*31 + +typedef struct TIMER { + char name[32]; +} Timer; + +typedef struct { + unsigned int nument; + Timer **entries; +} Hashentry; + +static Hashentry hashtable[tablesiz]; /* table of entries hashed by sum of chars */ + +Timer longnames_samehash[] = { + "9123456789012345678901234567890", + "9234567890123456789012345678901", + "9345678901234567890123456789012", + "9456789012345678901234567890123", + "9567890123456789012345678901234" +}; + +Timer longnames_diffhash[] = { + "0123456789012345678901234567890", + "1234567890123456789012345678901", + "2345678901234567890123456789012", + "3456789012345678901234567890123", + "4567890123456789012345678901234" +}; + +Timer shortnames_samehash[] = { + "mn", + "lo", + "kp", + "jq", + "ir" +}; + +Timer shortnames_diffhash[] = { + "ab", + "cd", + "ef", + "gh", + "ij" +}; + +static int numstr = sizeof (shortnames_diffhash) / sizeof (Timer); + +inline static void *getentry (const Hashentry *, const char *, int *); static void overhead (int, int); +int gethashvalue (char *); int main () { @@ -86,17 +135,6 @@ static void overhead (int iter, int ninvoke) struct tms buf; void *nothing; - GPTLstart ("mallocstuff"); - strings1 = (char **) malloc (ninvoke * sizeof (char *)); - strings2 = (char **) malloc (ninvoke * sizeof (char *)); - for (i = 0; i < ninvoke; ++i) { - strings1[i] = (char *) malloc (8); - strings2[i] = (char *) malloc (8); - sprintf (strings1[i], "str%3d", i); - sprintf (strings2[i], "str%3d", i); - } - GPTLstop ("mallocstuff"); - #ifdef THREADED_OMP GPTLstart ("get_thread_num"); for (i = 0; i < ninvoke; ++i) { @@ -117,26 +155,6 @@ static void overhead (int iter, int ninvoke) } GPTLstop ("times"); - GPTLstart ("getentry"); - for (i = 0; i < ninvoke; ++i) { - nothing = getentry (strings1[i], strings2[i], &indx); - } - GPTLstop ("getentry"); - - GPTLstart ("freestuff"); - for (i = 0; i < ninvoke; ++i) { - free (strings1[i]); - free (strings2[i]); - } - free (strings1); - free (strings2); - GPTLstop ("freestuff"); - - for (i = 0; i < ninvoke; ++i) { - GPTLstart ("2or4PAPI_reads"); - GPTLstop ("2or4PAPI_reads"); - } - struct timeval tp1, tp2; /* argument returned from gettimeofday */ float overhead; @@ -167,28 +185,111 @@ static void overhead (int iter, int ninvoke) overhead = (tp2.tv_sec - tp1.tv_sec) + 1.e-6*(tp2.tv_usec - tp1.tv_usec); printf ("overhead = %f sec. Compare to 'overhead_est' in timing output\n", overhead); - /* - for (i = 0; i < ninvoke/10; ++i) { - gettimeofday (&tp1, 0); - gettimeofday (&tp2, 0); - overhead = (tp2.tv_sec - tp1.tv_sec) + - 1.e-6*(tp2.tv_usec - tp1.tv_usec); - printf ("tp2.tv_usec diff=%d\n", tp2.tv_usec - tp1.tv_usec); + + Timer **eptr; + int nument; + + for (i = 0; i < numstr; i++) { + indx = gethashvalue (shortnames_diffhash[i].name); + assert (indx < tablesiz); + ++hashtable[indx].nument; + nument = hashtable[indx].nument; + eptr = (Timer **) realloc (hashtable[indx].entries, nument * sizeof (Timer *)); + hashtable[indx].entries = eptr; + hashtable[indx].entries[nument-1] = &shortnames_diffhash[i]; + + indx = gethashvalue (shortnames_samehash[i].name); + assert (indx < tablesiz); + ++hashtable[indx].nument; + nument = hashtable[indx].nument; + eptr = (Timer **) realloc (hashtable[indx].entries, nument * sizeof (Timer *)); + hashtable[indx].entries = eptr; + hashtable[indx].entries[nument-1] = &shortnames_samehash[i]; + + indx = gethashvalue (longnames_diffhash[i].name); + assert (indx < tablesiz); + ++hashtable[indx].nument; + nument = hashtable[indx].nument; + eptr = (Timer **) realloc (hashtable[indx].entries, nument * sizeof (Timer *)); + hashtable[indx].entries = eptr; + hashtable[indx].entries[nument-1] = &longnames_diffhash[i]; + + indx = gethashvalue (longnames_samehash[i].name); + assert (indx < tablesiz); + ++hashtable[indx].nument; + nument = hashtable[indx].nument; + eptr = (Timer **) realloc (hashtable[indx].entries, nument * sizeof (Timer *)); + hashtable[indx].entries = eptr; + hashtable[indx].entries[nument-1] = &longnames_samehash[i]; + } + + GPTLstart ("getentry_shortnames_diffhash"); + for (i = 0; i < ninvoke; ++i) { + nothing = getentry (hashtable, "mn", &indx); + assert (indx < tablesiz); + if ( ! nothing) + printf ("error: index not found"); } - */ + GPTLstop ("getentry_shortnames_diffhash"); + + GPTLstart ("getentry_shortnames_samehash"); + for (i = 0; i < ninvoke; ++i) { + nothing = getentry (hashtable, "mn", &indx); + assert (indx < tablesiz); + if ( ! nothing) + printf ("error: index not found"); + } + GPTLstop ("getentry_shortnames_samehash"); + + GPTLstart ("getentry_longnames_diffhash"); + for (i = 0; i < ninvoke; ++i) { + nothing = getentry (hashtable, "4567890123456789012345678901234", &indx); + assert (indx < tablesiz); + if ( ! nothing) + printf ("error: index not found"); + } + GPTLstop ("getentry_longnames_diffhash"); + + GPTLstart ("getentry_longnames_samehash"); + for (i = 0; i < ninvoke; ++i) { + nothing = getentry (hashtable, "9567890123456789012345678901234", &indx); + assert (indx < tablesiz); + if ( ! nothing) + printf ("error: index not found"); + } + GPTLstop ("getentry_longnames_samehash"); } -static void *getentry (char *string, - char *name, - int *indx) +static inline void *getentry (const Hashentry *hashtable, + const char *name, + int *indx) { - char *c = name; + int i; + + const char *c = name; for (*indx = 0; *c; c++) *indx += *c; - if (strcmp (name, string) == 0) - return (void *) c; + for (i = 0; i < hashtable[*indx].nument; i++) + if (strcmp (name, hashtable[*indx].entries[i]->name) == 0) + return hashtable[*indx].entries[i]; return 0; } + +int gethashvalue (char *name) +{ + int i; + int indx; + + const char *c = name; + + for (indx = 0; *c; c++) + indx += *c; + + return indx; +} + + +