⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 esmc_timer.c

📁 CCSM Research Tools: Community Atmosphere Model (CAM)
💻 C
📖 第 1 页 / 共 3 页
字号:
	  break;		default:	  break;	}      }#endif      ++nevent;    }  }#ifdef HAVE_PCL  if (ncounter > 0) {    int thread;         /* thread number */    nbytes = numthreads * sizeof (PCL_DESCR_TYPE);    if ((descr = (PCL_DESCR_TYPE *) malloc (nbytes)) == 0)      return t_error ("malloc failure: %d items\n", numthreads);    /*    ** PCLinit must be called on a per-thread basis.  Therefore must make the call here    ** rather than in t_initialize.  null timer list flags not initialized.    ** Also, the critical section is necessary because PCLstart appears not to be    ** thread-safe.    */#pragma omp parallel for        for (thread = 0; thread < numthreads; thread++) {      unsigned int flags;           /* mode flags needed by PCL */#pragma omp critical      {	if ((ret = PCLinit (&descr[thread])) != PCL_SUCCESS)	  return t_error ("unable to allocate PCL handle for thread %d. %s\n",			  thread, t_pclstr (ret));	/*	** Always count user mode only	*/      	flags = PCL_MODE_USER;	if ((ret = PCLquery (descr[thread], counter_list, ncounter, flags)) != PCL_SUCCESS)	  return t_error ("Bad return from PCLquery thread %d: %s\n", thread, t_pclstr (ret));	if ((ret = PCLstart (descr[thread], counter_list, ncounter, flags)) != PCL_SUCCESS)	  return t_error ("PCLstart failed thread=%d: %s\n", thread, t_pclstr (ret));      }    }  }#endif  t_initialized = true;#endif  return 0;}static char *t_pclstr (int code){#if ( defined DISABLE_TIMERS )  return "";#endif#ifdef HAVE_PCL  switch (code) {  case PCL_SUCCESS:     return "Success";      case PCL_NOT_SUPPORTED:    return "Event not supported";      case PCL_TOO_MANY_EVENTS:    return "Too many events";      case PCL_TOO_MANY_NESTINGS:    return "More nesting levels than allowed";      case PCL_ILL_NESTING:    return "Bad nesting";      case PCL_ILL_EVENT:    return "Illegal event identifier";      case PCL_MODE_NOT_SUPPORTED:    return "Mode not supported";      case PCL_FAILURE:    return "Failure for unspecified reason";      default:    return "Unknown error code";      }#endif    return "Unknown error code";}        /*** t_pr: print stats for all known timers to a file**** Input arguments:**   procid: Designed for MPI jobs to give a unique output file name, **     normally the MPI logical process id.**** Return value: 0 (success) or -1 (failure)*/static int mhz;            /* processor clock rate (from pcl library) */static int t_pr (ESMC_Log log, char *name, int procid){  char outfile[11];        /* name of output file: timing.xxx */			     int indent;              /* index over number indentation levels */  int thread;              /* thread index */  int ilstart;             /* index over indentation level */  int n;  double gttdcost;         /* cost of a single gettimeofday call */  double deltat;           /* time difference between 2 calls to gettimeofday */  struct Stats stats;      /* per timer stats */  struct Stats threadsum;  /* timer sum over threads */			     struct node *ptr, *tptr; /* linked list pointers */			     FILE *fp;                /* output file pointer */  struct timeval tp1, tp2; /* input to gettimeofday() */  struct tms buf;          /* input to times() */#if ( defined DISABLE_TIMERS )  return 0;#endif  if ( ! t_initialized)    return t_error ("t_pr: t_initialize has not been called\n");  /*  ** Only allow the master thread to print stats  */  if (get_thread_num () != 0)    return 0;  /*  ** Estimate wallclock timer overhead: 4 times the cost of a call to gettimeofday  ** (since each start/stop pair involves 4 such calls).  */  gettimeofday (&tp1, NULL);  gettimeofday (&tp2, NULL);  gttdcost = 1.e6*(tp2.tv_sec  - tp1.tv_sec) + (tp2.tv_usec - tp1.tv_usec);  ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "Wallclock timer cost est.: %8.3f usec per start/stop pair\n", 	      gttdcost*4.);  /*  ** CPU cost estimate: 2 times the cost of a call to times().  Subtract the  ** cost of a single gettimeofday call to improve the estimate.  */  if (usrsysenabled) {    gettimeofday (&tp1, NULL);    (void) times (&buf);    gettimeofday (&tp2, NULL);    deltat = 1.e6*(tp2.tv_sec  - tp1.tv_sec) + (tp2.tv_usec - tp1.tv_usec);    ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "CPU timer cost est.:       %8.3f usec per start/stop pair\n", 		2.*deltat - gttdcost);  }      ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "CPU accumulation interval is %g seconds\n",           1./(float) ticks_per_sec);#ifdef HAVE_PCL  mhz = PCL_determine_mhz_rate();  ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "Clock speed is %d MHz\n", mhz);#endif  for (thread = 0; thread < numthreads; thread++) {    /*    ** Only print heading for threads that have 1 or more items to report    */    if (timers[thread] == NULL) continue;    ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "\nStats for thread %d:\n", thread);    print_header (log, max_indent_level[thread]);    for (ptr = timers[thread]; ptr != NULL; ptr = ptr->next) {      if (ptr->onflg) {	ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "Timer %s was not off.  No stats will be printed\n",		 ptr->name);      } else {	fillstats (&stats, ptr);	/*	** Print stats indented.  If indent_level = AMBIGUOUS (a negative 	** number) the name will be printed with no indentation.	*/	for (indent = 0; indent < ptr->indent_level; indent++)	  ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "  ");	ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "%-15s", ptr->name);	/*	** If indent_level = AMBIGUOUS (a negative number) we want to loop 	** from 0	*/	ilstart = MAX (0, ptr->indent_level);	for (indent = ilstart; indent < max_indent_level[thread]; indent++)	  ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "  ");	print_stats_line (log, &stats);      }    }    if (usrsysenabled || wallenabled)      ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "\nTIMER OVERHEAD (wallclock seconds) = %12.6f\n", 	       overhead[thread]);    if (pcl_cyclesenabled)      ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "TIMER OVERHEAD (cycles) = %12.6e\n", 	       (double) overhead_pcl[thread]);  }  /*  ** Print a vertical summary if data exist for more than 1 thread.  The "2"  ** passed to print_header is so we'll get an extra 4 spaces of indentation  ** due to the thread number appended to the timer name.  */  if (numthreads > 0 && timers[1] != NULL) {    ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "\nSame stats sorted by timer with thread number appended:\n");    print_header (log, 2);    /*    ** Print stats for slave threads that match master    */    for (ptr = timers[0]; ptr != NULL; ptr = ptr->next) {      char name[20];      Boolean found = false;      /*      ** Don't bother printing summation stats when only the master thread      ** invoked the timer      */      for (thread = 1; thread < numthreads; thread++)	for (tptr = timers[thread]; tptr != NULL; tptr = tptr->next) {	  if (STRMATCH (ptr->name, tptr->name))	    found = true;	}      if ( ! found) continue;      /*      ** Initialize stats which sum over threads      */      memset (&threadsum, 0, sizeof (threadsum));      if ( ! ptr->onflg) {	fillstats (&stats, ptr);	strcpy (name, ptr->name);	strcat (name, ".0");	ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "%-19s", name);	print_stats_line (log, &stats);	threadsum = stats;      }      /*      ** loop over slave threads, printing stats for each and accumulating      ** sum over threads when the name matches      */      for (thread = 1; thread < numthreads; thread++) {	for (tptr = timers[thread]; tptr != NULL; tptr = tptr->next) {	  if (STRMATCH (ptr->name, tptr->name)) {	    if ( ! tptr->onflg) {	      char num[5];	      fillstats (&stats, tptr);	      strcpy (name, tptr->name);	      sprintf (num, ".%-3d", thread);	      strcat (name, num);	      ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "%-19s", name);	      print_stats_line (log, &stats);	      threadsum.usr      += stats.usr;	      threadsum.sys      += stats.sys;	      threadsum.usrsys   += stats.usrsys;	      threadsum.elapse   += stats.elapse;	      threadsum.max_wtime = MAX (threadsum.max_wtime, stats.max_wtime);	      threadsum.min_wtime = MIN (threadsum.min_wtime, stats.min_wtime);	      threadsum.count    += stats.count;	      for (n = 0; n < ncounter; n++)		threadsum.pcl_result[n] += stats.pcl_result[n];	    }	    break; /* Go to the next thread */	  }        /* if (STRMATCH (ptr->name, tptr->name) */	}          /* loop thru linked list of timers for this thread */      }            /* loop over slave threads */      strcpy (name, ptr->name);      strcat (name, ".sum");      ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "%-19s", name);      print_stats_line (log, &threadsum);      ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "\n");    } /* loop through master timers */    for (thread = 0; thread < max_seen_thread + 1; thread++) {      if (usrsysenabled || wallenabled)	ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "OVERHEAD.%-3d (wallclock seconds) = %12.6f\n", 		 thread, overhead[thread]);      if (pcl_cyclesenabled)	ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "OVERHEAD.%-3d (cycles) = %12.6e\n", 		 thread, (double) overhead_pcl[thread]);    }  } /* if (numthreads > 0 && timers[1] != NULL */  return 0;}static void fillstats(struct Stats *stats, struct node *ptr){  int n;  stats->usr       = ptr->accum_utime / (float) ticks_per_sec;  stats->sys       = ptr->accum_stime / (float) ticks_per_sec;  stats->usrsys    = stats->usr + stats->sys;  stats->elapse    = ptr->accum_wtime_sec + 1.e-6 * ptr->accum_wtime_usec;  stats->max_wtime = ptr->max_wtime;  stats->min_wtime = ptr->min_wtime;  stats->count     = ptr->count;  for (n = 0; n < ncounter; n++)    stats->pcl_result[n] = ptr->accum_pcl_result[n];}static void print_stats_line(ESMC_Log log, struct Stats *stats){  int index;  int n;  long long cycles;  long long instr;  long long flops;  long long loadstore;  long long l2cache;  long long jump;  float mflops;  float ipc;  float memfp;  ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "%9ld ", stats->count);  if (usrsysenabled)    ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "%9.3f %9.3f %9.3f ", stats->usr, stats->sys, stats->usrsys);  if (wallenabled)    ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "%9.3f %9.3f %9.3f ", stats->elapse, stats->max_wtime, 	     stats->min_wtime);    for (n = 0; n < nevent; n++) {    if (event[n]->name > pcl_start && event[n]->name < pcl_end) {      index = event[n]->index;      if (stats->pcl_result[index] > 1.e6)	ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "%9.3e ", (double) stats->pcl_result[index]);      else	ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "%9ld ", (long) stats->pcl_result[index]);    }  }  ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "\n");}static void print_header (ESMC_Log log, int indent_level){  int i;  int n;  ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "Name           ");  for (i = 0; i < indent_level; i++)    ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "  ");  ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "Called    ");  if (usrsysenabled)    ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "Usr       Sys       Usr+Sys   ");  if (wallenabled)    ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "Wallclock Max       Min       ");  for (n = 0; n < nevent; n++)    if (event[n]->name > pcl_start && event[n]->name <= pcl_end)      ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, event[n]->string);  ESMC_LogPrint(log, ESMC_LOGLEVEL_TIMER, "\n");}/*** t_reset: reset all known timers to 0**** Return value: 0 (success) or -1 (failure)*/static int t_reset (){  int n;             /* index over threads */  struct node *ptr;  /* linked list index */#if ( ! defined DISABLE_TIMERS )  if ( ! t_initialized)    return t_error ("t_reset: t_initialize has not been called\n");  /*  ** Only allow the master thread to reset timers  */  if (get_thread_num () != 0)    return 0;  for (n = 0; n < numthreads; n++) {    for (ptr = timers[n]; ptr != NULL; ptr = ptr->next) {      memset (timers[n], 0, sizeof (struct node));      printf ("Reset accumulators for timer %s to zero\n", ptr->name);    }  }#endif  return 0;}/*** t_setoption: set option value to true or false.**** Input arguments:**   option: option to be set**   val:    value to which option should be set**** Return value: 0 (success) or -1 (failure)*/static int t_setoption (OptionName option, Boolean val){  int n;#if ( defined DISABLE_TIMERS )  return 0;#endif  if (t_initialized)    return (t_error ("t_setoption: Options must be set BEFORE t_initialize\n"));  for (n = 0; n < npossible; n++) {    if (possible_event[n].name == option) {      possible_event[n].enabled = val;      if (val)	printf ("t_setoption: option enabled:  %s\n", possible_event[n].string);      else	printf ("t_setoption: option disabled: %s\n", possible_event[n].string);      return 0;    }  }  return (t_error ("t_setoption: Option with enum index %d not available\n",		     option));}/*** t_stamp: Compute timestamp of usr, sys, and wallclock time (seconds)**** Output arguments:**   wall: wallclock**   usr:  user time**   sys:  system time**** Return value: 0 (success) or -1 (failure)*/static int t_stamp (double *wall, double *usr, double *sys){  struct timeval tp;         /* argument to gettimeofday */  struct tms buf;            /* argument to times */  *usr = 0;  *sys = 0;  if (times (&buf) == -1)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -