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

📄 cachebench.c

📁 这是micrel公司宽带路由ARM9芯片的VXWORKS BSP 源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Header: /cvs/homes/llcbench/llcbench/cachebench/cachebench.c,v 1.1 2000/06/09 19:15:38 mucci Exp $ 
 * $Log: cachebench.c,v $
 * Revision 1.1  2000/06/09 19:15:38  mucci
 * Full blown CVS commit
 * Revision 1.4  1998/03/31 05:52:14  mucci
 * Added RCS Keywords
 */
#include "vxWorks.h"
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include "sys/times.h"
#include <sys/types.h>
#include <fcntl.h>
#include <time.h>
#include <assert.h>
#include <unistd.h>
#include <memLib.h>
#include <string.h>
/* #include <malloc.h> */

static struct timeval tv1, tv2;

#define TIMER_START     go(1);gettimeofday(&tv1, (struct timezone*)0)
#define TIMER_STOP      gettimeofday(&tv2, (struct timezone*)0)
#define TIMER_ELAPSED_US	(double)(((tv2.tv_usec-tv1.tv_usec)+((tv2.tv_sec-tv1.tv_sec)*1000000)))

#define ARRAY(x,i,j,m) *(x+((j)*m)+(i))

#ifdef REGISTER
#undef REGISTER
#define REGISTER register
#else
#define REGISTER
#endif

#if defined(USE_DOUBLE)
#ifndef DATATYPE
#define DATATYPE double
#define DATASTRING "double"
#endif
#elif defined(USE_INT)
#ifndef DATATYPE
#define DATATYPE int
#define DATASTRING "int"
#endif
#elif defined(USE_CHAR)
#ifndef DATATYPE
#define DATATYPE char
#define DATASTRING "char"
#endif
#elif defined(USE_FLOAT)
#ifndef DATATYPE
#define DATATYPE float
#define DATASTRING "float"
#endif
#endif

#ifndef DATATYPE
 #if 0	/* Change default type to INT */
  #define DATATYPE double
  #define DATASTRING "double"
 #else
  #define DATATYPE int
  #define DATASTRING "int"
 #endif	/* Change default type to INT */
#endif

#ifdef DEBUG
#define DBG(a) a;
#else
#define DBG(a)
#endif

#define READONLY 1<<0
#define WRITEONLY 1<<1
#define READWRITE 1<<2
#define NOCALIBRATE 1<<3
#define GUESSCACHESIZE 1<<4
#define MEMORYSET 1<<5
#define MEMORYCOPY 1<<6
#define HANDTUNED 1<<7

/* DEFAULT SETTINGS */

#define CACHE_MIN_BITS (8) /* 1<<bits is smallest cache in bytes */
#define CACHE_MAX_BITS (24) /* 1<<bits is largest cache in bytes */
#define CACHE_MIN (1<<CACHE_MIN_BITS)
#define CACHE_MAX (1<<CACHE_MAX_BITS)
#define RESOLUTION (2)
#define TIME_SLOTS (2*(CACHE_MAX_BITS-CACHE_MIN_BITS+1))
#define MEASURE_TIME 5
#define DOUBLE_NS(x) ((double)x)*1.0e9
#define THRESHOLD (0.9) /* 1st level must be faster than 2nd level */
#define REPEAT_COUNT 2

extern char *optarg;

int logmemsize = CACHE_MAX_BITS, memsize = 1<<CACHE_MAX_BITS, repeat_count = REPEAT_COUNT;
int resolution = RESOLUTION, timeslots, duration = MEASURE_TIME, type = NOCALIBRATE;

volatile int keepgoing;

void flushall(int yes)
{
  static char *buffer = NULL;
  static char val = 1;

  if (yes)
    {
      if (buffer == NULL)
	assert(buffer = (char *)malloc(memsize*sizeof(char)));
      memset(buffer,val++,memsize);
    }
  else
    free(buffer);
}

int go(int a)
{
  if (a==-1)
    return(keepgoing);
  else
    return(keepgoing = a);
}

void handler(int a)
{
  go(0);
}

void compute_stats(int i, int j, double refcnt, double overhead_per_ref,
		   double *times, double *bws, double *percents, int *sizes,
		   double tmicrosec, int datasize)
{
  ARRAY(times,i,j,repeat_count) = 
    ((tmicrosec*1000.0) - (refcnt*overhead_per_ref))/refcnt;

  ARRAY(bws,i,j,repeat_count) = 
    ((refcnt*datasize)/(1024.0*1024.0)) / 
    ((ARRAY(times,i,j,repeat_count)*refcnt)/1.0E9);

  if (i == 0)
    {
      if (j == 0)
	ARRAY(percents,i,j,repeat_count) = 1.0;
      else
	{
	  ARRAY(percents,i,j,repeat_count) = 
	    ARRAY(times,i,j,repeat_count) / 
	    ARRAY(times,i,j-1,repeat_count);
	}
    }
  else
    {
      if (j == 0)
	{
	  ARRAY(percents,i,j,repeat_count) = 
	    ARRAY(times,i,j,repeat_count) / 
	    ARRAY(times,i-1,repeat_count-1,repeat_count);
	}
      else
	{
	  ARRAY(percents,i,j,repeat_count) = 
	    ARRAY(times,i,j,repeat_count) / 
	    ARRAY(times,i,j-1,repeat_count);
	}
    }

  if (isatty(1))
    {
      printf("%-15d %-15.2f %-15.2f %-15.2f\n", 
	       sizes[i],
	       ARRAY(times,i,j,repeat_count),
	       ARRAY(bws,i,j,repeat_count),
	       ARRAY(percents,i,j,repeat_count));
    }
  else
    printf("%d %f\n", 
	   sizes[i],
	   ARRAY(bws,i,j,repeat_count));
  sleep(1);
}

void compute_cache_sizes(double *times, double *bws, double *percents, int *sizes)
{
  int i, maxb = 0, maxa = 0, cachea, cacheb;

  /* Look for 2 highest percentages */

  for (i=0; i < timeslots; i++)
    if (percents[i] > percents[maxa])
      maxa = i;

  for (i=0; i < timeslots; i++)
    {
      if ((i != maxa) && (percents[i] > percents[maxb]))
	{
	  maxb = i;
	}
    }

  printf("\n\t\t\tCache Capacity Analysis\n\n");
  
  if (1.0/percents[maxa] >= THRESHOLD)
    {
      printf("No L1 limit found, must be larger than %d bytes.\n",memsize);
      return;
    }
    
  /* Set them to the index if the entry for that cache size */
  /* Remember our percents are relative to the previous entry */

  cachea = sizes[maxa-1];
  cacheb = sizes[maxb-1];

  if (cachea > cacheb)
    printf("Level 1 Cache: %d bytes\n",cachea);
  else
    {
      printf("Level 1 Cache: %d bytes\n",cachea);
      if ((times[maxa]/times[maxb] < THRESHOLD) && (1.0/percents[maxb] < THRESHOLD))
	printf("Level 2 Cache: %d bytes\n",cacheb);
    }
}

int usage(int argc, char **argv)
{
  int c;
  int errflg = 0;

  while ((c = getopt(argc, argv, "m:d:hrwbcsptx:e:")) != -1)
    switch (c) {
    case 'm':
      if (((logmemsize = atoi(optarg)) < 0) || (logmemsize <= CACHE_MIN_BITS))
	errflg++;
      memsize = 1<<logmemsize;
      break;
    case 'd':
      if ((duration = atoi(optarg)) < 0)
	errflg++;
      break;
    case 's':
      type |= MEMORYSET;
      break; 
    case 'p':
      type |= MEMORYCOPY;
      break; 
    case 'r':
      type |= READONLY;
      break; 
    case 'h':
      errflg++;
      break; 
    case 't':
      type |= HANDTUNED;
      break;
    case 'w':
      type |= WRITEONLY;
      break; 
    case 'b':
      type |= READWRITE;
      break; 
    case 'c':
      type ^= NOCALIBRATE;
      break; 
    case 'g':
      type |= GUESSCACHESIZE;
      break; 
    case 'x':
      if ((resolution = atoi(optarg)) < 0)
	errflg++;
      resolution++; /* Correct for my usage */
      break; 
    case 'e':
      if ((repeat_count = atoi(optarg)) <= 0)
	errflg++;
      break; 
    case '?':
      errflg++;
      break; }

  if ((type & (READONLY|WRITEONLY|READWRITE|MEMORYCOPY|MEMORYSET)) == 0)
    {
      if (isatty(1))
	type |= READONLY|WRITEONLY|READWRITE|MEMORYCOPY|MEMORYSET;
      else
	type |= READWRITE;
    }
  
  if (errflg) 
    {
      fprintf(stderr, "Usage: %s -rwbtsp [-x #] [-m #] [-d #] [-e #]\n",argv[0]);
      fprintf(stderr, "\t -r Read benchmark\n");
      fprintf(stderr, "\t -w Write benchmark\n");
      fprintf(stderr, "\t -b Read/Modify/Write benchmark\n");
      fprintf(stderr, "\t -t Use hand tuned versions of the above\n");
      fprintf(stderr, "\t -s memset() benchmark\n");
      fprintf(stderr, "\t -p memcpy() benchmark\n");
      /* fprintf(stderr, "\t -c Enable calibration code\n"); 
      fprintf(stderr, "\t -g Enable cache size guessing code\n"); */
      fprintf(stderr, "\t -x Number of measurements between powers of 2.\n");
      fprintf(stderr, "\t -m Specify the log2(available physical memory)\n");
      fprintf(stderr, "\t -d Number of seconds per iteration\n");
      fprintf(stderr, "\t -e Repeat count per cache size\n\n");
      fprintf(stderr, "Datatype used is %s, %d bytes.\n",DATASTRING,(int)sizeof(DATATYPE));
      fprintf(stderr, "Defaults if  tty: -rwbsp -x%d -m%d -d%d -e%d\n",
	      RESOLUTION-1,CACHE_MAX_BITS,MEASURE_TIME,REPEAT_COUNT);
      fprintf(stderr, "Defaults if file: -b   -x%d -m%d -d%d -e1\n",
	      RESOLUTION-1,CACHE_MAX_BITS,MEASURE_TIME);
      exit(1);
    }

  timeslots = resolution*(logmemsize - CACHE_MIN_BITS) + 1;

  DBG(printf("%d %d %d %d\n",logmemsize,memsize,duration,timeslots)); 

  return(type);
}

void fake_out_optimizations(DATATYPE *x, int bytes)
{
  static int fd = -1;

  if (fd == -1)
    assert(fd=open("/dev/null",O_WRONLY));
  assert(write(fd,(void *)x,bytes)!=-1);
}

/* double calibrate_benchmark_ronly(REGISTER DATATYPE *x, REGISTER int limit, int *oloops, double *ous)
{
  REGISTER int index = 0, loops = 0;
  REGISTER DATATYPE sum = 0, foolem = 0;
  
  flushall(x);
  keepgoing = 1;
  assert(signal(SIGALRM,handler) != SIG_ERR);
  limit -= 4; foolem = (DATATYPE)limit;

  alarm(duration);
  TIMER_START;
again:
  sum += foolem + foolem+(DATATYPE)1 + foolem+(DATATYPE)2 + foolem+(DATATYPE)3;
  if (((index+=4) < limit) && (keepgoing))
    goto again;
  else if (keepgoing)
    {
      index = 0;
      loops++;
      goto again;
    }
  TIMER_STOP;
  index += 4;

  x[0] = (DATATYPE)sum;
  x[1] = (DATATYPE)index;
  fake_out_optimizations(x,2*sizeof(DATATYPE));

  *oloops = loops;
  *ous = TIMER_ELAPSED_US;
  return(((double)loops*(double)limit)+(double)index);  
}

double calibrate_benchmark_wonly(REGISTER DATATYPE *x, REGISTER int limit, int *oloops, double *ous)
{
  REGISTER int index = 0, loops = 0;
  REGISTER DATATYPE sum1 = (DATATYPE)0, sum2 = (DATATYPE)0, sum3 = (DATATYPE)0, sum4 = (DATATYPE)0;

  flushall(x);
  keepgoing = 1;
  assert(signal(SIGALRM,handler) != SIG_ERR);
  limit -= 4; 

  alarm(duration);
  TIMER_START;
again:
  sum1++;
  sum2++;
  sum3++;
  sum4++;
  if (((index+=4) < limit) && (keepgoing))
    goto again;
  else if (keepgoing)
    {
      index = 0;
      loops++;
      goto again;
    }
  TIMER_STOP;
  index += 4;

  x[0] = (DATATYPE)sum1;
  x[1] = (DATATYPE)sum2;
  fake_out_optimizations(x,2*sizeof(DATATYPE));
    
  return(((double)loops*(double)limit)+(double)index);
} 

double calibrate_benchmark(REGISTER DATATYPE *x, REGISTER int to_do_loops, REGISTER int limit, double *ous)
{
  REGISTER int index = 0, loops = 0;
  REGISTER DATATYPE sum1 = (DATATYPE)0;

  TIMER_START;
  while (loops < to_do_loops)
    {
      for (index = 0; index < limit; index++)
	{
	  sum1++;
	}
      loops++;
    }
  TIMER_STOP;

  x[0] = (DATATYPE)sum1;
  x[1] = (DATATYPE)index;
  fake_out_optimizations(x,2*sizeof(DATATYPE));
    
  *ous = TIMER_ELAPSED_US;
  {
    double refcnt = ((double)loops*(double)limit)+(double)index;
    DBG(fprintf(stderr,"C: %d loops at limit %d took %f us, %f refs.\n",loops,limit,*ous,refcnt));
    return(refcnt);
  }
} */

double benchmark_cache_ronly(REGISTER DATATYPE *x, REGISTER int limit, int *oloops, double *ous)
{
  REGISTER int index = 0, loops = 0;
  REGISTER DATATYPE sum = (DATATYPE)0;

  flushall(1);
  assert(signal(SIGALRM,handler) != SIG_ERR);

  alarm(duration);
  TIMER_START;

#ifdef SOLARIS
  while (go(-1))
#else
  while (keepgoing)
#endif  
    {
      for  (index = 0; index < limit; index++)
	{
	  sum += x[index];
	}
      loops++;
    }

  TIMER_STOP;

  x[0] = (DATATYPE)sum;
  x[1] = (DATATYPE)index;
  fake_out_optimizations(x,2*sizeof(DATATYPE));

  *oloops = loops;
  *ous = TIMER_ELAPSED_US;
  {
    double refcnt = ((double)loops*(double)limit)+(double)index;
    DBG(fprintf(stderr,"T: %d loops at limit %d took %f us, %f refs.\n",loops,limit,*ous,refcnt));
    return(refcnt);
  }
}

double hand_benchmark_cache_ronly(REGISTER DATATYPE *x, REGISTER int limit, int *oloops, double *ous)
{
  REGISTER int index = 0, loops = 0;
  REGISTER DATATYPE sum = (DATATYPE)0;
  REGISTER DATATYPE sum2 = (DATATYPE)0;

  flushall(1);
  keepgoing = 1;
  assert(signal(SIGALRM,handler) != SIG_ERR);
  limit -= 8;

  alarm(duration);
  TIMER_START;

again:
  sum += x[index] + x[index+1] + x[index+2] + x[index+3];
  sum2 += x[index+4] + x[index+5] + x[index+6] + x[index+7];
  if ((index += 8) < limit)
    goto again;
  else if (keepgoing)
    {
      index = 0;
      loops++;
      goto again;
    }

  TIMER_STOP;
  index += 8;

  x[0] = (DATATYPE)sum;
  x[1] = (DATATYPE)index;
  fake_out_optimizations(x,2*sizeof(DATATYPE));

  *oloops = loops;
  *ous = TIMER_ELAPSED_US;
  {
    double refcnt = ((double)loops*(double)limit)+(double)index;
    DBG(fprintf(stderr,"T: %d loops at limit %d took %f us, %f refs.\n",loops,limit,*ous,refcnt));
    return(refcnt);
  }
}

double benchmark_cache_wonly(REGISTER DATATYPE *x, REGISTER int limit, int *oloops, double *ous)
{
  REGISTER int index = 0, loops = 0;

⌨️ 快捷键说明

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