Azinix

perf.c

Go to the documentation of this file.
00001 #include "util.h"
00002 #include "timing.h"
00003 
00004 
00005 /**
00006   * \brief Testing the resolution of the rdtsc timing code
00007   */
00008 
00009 int
00010 Perf_CheckTimingCode (ClientData cd,
00011               Tcl_Interp * interp, int objc, Tcl_Obj * const objv[])
00012 {
00013   util_timing_t t0, t1;
00014 
00015   util_timing_set (&t0);
00016   util_timing_pause_secs (0.0000005);
00017   util_timing_set (&t1);
00018 
00019   util_timing_t diffTime;
00020 
00021   diffTime = util_timing_diff (t1, t0);
00022   printf (" high - %u\tlow - %u\n", diffTime.high, diffTime.low);
00023 
00024   double T = util_timing_secs (diffTime);
00025   printf ("diff time in ns is %f\n", 1000000000.0 * T);
00026   return TCL_OK;
00027 
00028 }
00029 
00030 
00031 
00032 /**
00033   * \brief  Routine to determine machine dependent parameters
00034   */
00035 
00036 int
00037 Perf_CheckHardware (ClientData cd,
00038             Tcl_Interp * interp, int objc, Tcl_Obj * const objv[])
00039 {
00040   printf ("This is 10 %d, and this is 010 %d\n", 10, 010);
00041   printf ("Size in bytes of onboard types:\n");
00042   printf ("char %d, short %d, int %d, long %d,",
00043       sizeof (char), sizeof (short), sizeof (int), sizeof (long));
00044   printf (" float %d, double %d, void* %d\n",
00045       sizeof (float), sizeof (double), sizeof (void *));
00046 
00047   // result on tyan is char 1, short 2, int 4, long 4, float 4, double 8, void* 4
00048   unsigned long Xlong;
00049   unsigned char *p;
00050   unsigned int i;
00051 
00052   // 11 22 33 44 big-endian
00053   // 44 33 22 11 little-endian
00054 
00055   Xlong = 0x11223344UL;
00056 
00057   p = (unsigned char *) &Xlong;
00058 
00059   for (i = 0; i < sizeof (long); i++)
00060     {
00061       printf ("%x ", *p++);
00062     }
00063   printf ("\n");
00064 
00065 #if BYTE_ORDER == LITTLE_ENDIAN
00066   printf
00067     ("#if BYTE_ORDER == LITTLE_ENDIAN check shows it's a Little endian machine\n");
00068 #endif
00069 
00070 #if BYTE_ORDER == BIG_ENDIAN
00071   printf
00072     ("#if BYTE_ORDER == BIG_ENDIAN check shows it's a Big endian machine\n");
00073 #endif
00074 
00075   // result on tyan is 44 33 22 11
00076 
00077   /* PoP fix for big-end/little-end problems is as follows: */
00078 
00079   // write:
00080 
00081   // unsigned short x;
00082   // putchar( x >> 8 ); // write high-order bytes
00083   // putchar( x & Oxff );  // write low-order bytes
00084 
00085   // read:
00086 
00087   // unsigned short x;
00088   // x = getchar() << 8; // read high-order bytes
00089   // x |= getchar & OxFF; // read low-order bytes
00090 
00091   unsigned int A = 1;
00092   char *pA = (char *) &A;
00093   printf
00094     ("A = %o ; A << 1 = %o ; A << 2 = %o ; A << 16 = %o ; A << 31 = %o\n", A,
00095      A << 1, A << 2, A << 16, A << 31);
00096   printf
00097     ("A = %ud ; A << 1 = %ud ; A << 2 = %ud ; A << 16 = %ud ; A << 31 = %ud\n",
00098      A, A << 1, A << 2, A << 16, A << 31);
00099 
00100   printf ("A = %x => *pA = %x ; *(pA+1)= %x ; *(pA+2) = %x ; *(pA+3)= %x\n",
00101       A, *pA, *(pA + 1), *(pA + 2), *(pA + 3));
00102   printf ("A = %x => *pA = %x ; *(pA-1)= %x ; *(pA-2) = %x ; *(pA-3)= %x\n",
00103       A, *pA, *(pA - 1), *(pA - 2), *(pA - 3));
00104 
00105   A = 1 << 3;
00106   printf ("A = %x => *pA = %x ; *(pA+1)= %x ; *(pA+2) = %x ; *(pA+3)= %x\n",
00107       A, *pA, *(pA + 1), *(pA + 2), *(pA + 3));
00108   printf ("A = %x => *pA = %x ; *(pA-1)= %x ; *(pA-2) = %x ; *(pA-3)= %x\n",
00109       A, *pA, *(pA - 1), *(pA - 2), *(pA - 3));
00110 
00111   return 0;
00112 }
00113 
00114 
00115 /**
00116   * \brief  Code from Jon Bentley's Programming Pearls book for measuring
00117   * times used by various C constructs.  http://www.cs.bell-labs.com/cm/cs/pearls/code.html
00118   *
00119   */
00120 
00121 // #include <stdio.h>
00122 // #include <time.h>
00123 // #include <stdlib.h>
00124 // #include <math.h>
00125 
00126 // const int MAXN=100000;
00127 #define MAXN 100000
00128 static int x[MAXN];
00129 static int startn = 5000;
00130 static int n;
00131 
00132 /* FUNCTIONS TO BE TIMED */
00133 
00134 static int
00135 intcmp (int *i, int *j)
00136 {
00137   return *i - *j;
00138 }
00139 
00140 #define swapmac(i, j) { t = x[i]; x[i] = x[j]; x[j] = t; }
00141 
00142 static void
00143 swapfunc (int i, int j)
00144 {
00145   int t = x[i];
00146   x[i] = x[j];
00147   x[j] = t;
00148 }
00149 
00150 #define maxmac(a, b) ((a) > (b) ? (a) : (b))
00151 
00152 static int
00153 maxfunc (int a, int b)
00154 {
00155   return a > b ? a : b;
00156 }
00157 
00158 
00159 /* WORKHORSE */
00160 
00161 #define T(s) printf("%s (n=%d)\n", s, n);
00162 #define TRIALS 5
00163 #define M(op)                           \
00164     printf(" %-22s", #op);              \
00165     k = 0;                              \
00166     timesum = 0;                        \
00167     for (ex = 0; ex < TRIALS; ex++) {   \
00168         start = clock();                \
00169         for (i = 1; i <= n; i++) {      \
00170             fi = (float) i;             \
00171             for (j = 1; j <= n; j++) {  \
00172                 op;                     \
00173             }                           \
00174         }                               \
00175         t = clock()-start;              \
00176         printf("%6d", t);               \
00177         timesum += t;                   \
00178     }                                   \
00179     nans = 1e9 * timesum / ((double)    \
00180         n*n * TRIALS * CLOCKS_PER_SEC); \
00181     printf("%8.0f\n", nans);
00182 
00183 
00184 int
00185 Perf_TimePerf (ClientData cd,
00186            Tcl_Interp * interp, int objc, Tcl_Obj * const objv[])
00187 {
00188   int i, j, k;
00189   float fi, fj, fk;
00190   int t, ex, timesum, start, globalstart;
00191   double nans;
00192   globalstart = clock ();
00193   for (i = 0; i < n; i++)
00194     x[i] = rand ();
00195   n = startn;
00196   printf ("C Time Cost Model, n=%d\n", n);
00197   printf ("CLOCKS_PER_SEC = %d\n", CLOCKS_PER_SEC);
00198   T ("Integer Arithmetic");
00199   M (
00200       {
00201       }
00202   );
00203   M (k++);
00204   M (k = i + j);
00205   M (k = i - j);
00206   M (k = i * j);
00207   M (k = i / j);
00208   M (k = i % j);
00209   M (k = i & j);
00210   M (k = i | j);
00211   T ("Floating Point Arithmetic");
00212   M (fj = j;
00213     );
00214   M (fj = j;
00215      fk = fi + fj;
00216     );
00217   M (fj = j;
00218      fk = fi - fj;
00219     );
00220   M (fj = j;
00221      fk = fi * fj;
00222     );
00223   M (fj = j;
00224      fk = fi / fj;
00225     );
00226   T ("Array Operations");
00227   M (k = i + j);
00228   M (k = x[i] + j);
00229   M (k = i + x[j]);
00230   M (k = x[i] + x[j]);
00231   T ("Comparisons");
00232   M (if (i < j) k++);
00233   M (if (x[i] < x[j]) k++);
00234   T ("Array Comparisons and Swaps");
00235   M (k = (x[i] < x[k]) ? -1 : 1);
00236   M (k = intcmp (x + i, x + j));
00237   M (swapmac (i, j));
00238   M (swapfunc (i, j));
00239   T ("Max Function, Macro and Inline");
00240   M (k = (i > j) ? i : j);
00241   M (k = maxmac (i, j));
00242   M (k = maxfunc (i, j));
00243   n = startn / 5;
00244   T ("Math Functions");
00245   M (fk = j + fi;
00246     );
00247   M (k = rand ();
00248     );
00249   M (fk = sqrt (j + fi));
00250   M (fk = sin (j + fi));
00251   M (fk = sinh (j + fi));
00252   M (fk = asin (j + fi));
00253   M (fk = cos (j + fi));
00254   M (fk = tan (j + fi));
00255   n = startn / 10;
00256   T ("Memory Allocation");
00257   M (free (malloc (16));
00258     );
00259   M (free (malloc (100));
00260     );
00261   M (free (malloc (2000));
00262     );
00263 
00264   /* Possible additions: input, output, malloc */
00265   printf ("  Secs: %4.2f\n",
00266       ((double) clock () - globalstart) / CLOCKS_PER_SEC);
00267   return TCL_OK;
00268 }
00269 
00270 
00271 /**
00272   * \brief Code for testing space usage of various C constructs.  From
00273   * Bentley (see above).
00274   */
00275 
00276 #define MEASURE(T, text) {                  \
00277     printf("%s\t", text );      \
00278     printf("sizeof(%s) = %d\t", #T, sizeof(T) );                \
00279     int lastp = 0;                          \
00280     int i;  \
00281     for (i = 0; i < 11; i++) {          \
00282         T *p = (T *) malloc( sizeof( T ) );                     \
00283         int thisp = (int) p;                \
00284         if (lastp != 0)                     \
00285             printf(" %d ", thisp - lastp ); \
00286         lastp = thisp;                      \
00287     }                                       \
00288     printf("\n"); \
00289 }
00290 
00291 // Must use macros; templates give funny answers
00292 
00293 /*
00294 template <class T>
00295 void measure(char *text)
00296 {   cout << " measure: " << text << "\t";
00297     cout << sizeof(T) << "\n";
00298 }
00299 
00300 */
00301 typedef struct structc
00302 {
00303   char c;
00304 } structc;
00305 typedef struct structic
00306 {
00307   int i;
00308   char c;
00309 } structic;
00310 // struct structip { int i; structip *p; };
00311 typedef struct structip
00312 {
00313   int i;
00314   void *p;
00315 } structip;
00316 typedef struct structdc
00317 {
00318   double d;
00319   char c;
00320 } structdc;
00321 typedef struct structcd
00322 {
00323   char c;
00324   double d;
00325 } structcd;
00326 typedef struct structcdc
00327 {
00328   char c1;
00329   double d;
00330   char c2;
00331 } structcdc;
00332 typedef struct structiii
00333 {
00334   int i1;
00335   int i2;
00336   int i3;
00337 } structiii;
00338 typedef struct structiic
00339 {
00340   int i1;
00341   int i2;
00342   char c;
00343 } structiic;
00344 typedef struct structc12
00345 {
00346   char c[12];
00347 } structc12;
00348 typedef struct structc13
00349 {
00350   char c[13];
00351 } structc13;
00352 typedef struct structc28
00353 {
00354   char c[28];
00355 } structc28;
00356 typedef struct structc29
00357 {
00358   char c[29];
00359 } structc29;
00360 typedef struct structc44
00361 {
00362   char c[44];
00363 } structc44;
00364 typedef struct structc45
00365 {
00366   char c[45];
00367 } structc45;
00368 typedef struct structc60
00369 {
00370   char c[60];
00371 } structc60;
00372 typedef struct structc61
00373 {
00374   char c[61];
00375 } structc61;
00376 
00377 int
00378 Perf_SpacePerf (ClientData cd,
00379         Tcl_Interp * interp, int objc, Tcl_Obj * const objv[])
00380 {
00381 
00382 //      cout << "Raw sizeof";
00383 //      cout << "\nsizeof(char)="     << sizeof(char);  
00384 //      cout << "  sizeof(short)="    << sizeof(short);
00385 //      cout << "  sizeof(int)="      << sizeof(int);
00386 //      cout << "\nsizeof(float)="    << sizeof(float);
00387 //      cout << "  sizeof(struct *)=" << sizeof(structc *);
00388 //      cout << "  sizeof(long)="     << sizeof(long);
00389 //      cout << "\nsizeof(double)="   << sizeof(double);
00390   printf ("Raw sizeof\n");
00391   printf ("sizeof(char)=%d\n", sizeof (char));
00392   printf ("sizeof(short)=%d\n", sizeof (short));
00393   printf ("sizeof(int)=%d\n", sizeof (int));
00394   printf ("sizeof(float)=%d\n", sizeof (float));
00395   printf ("sizeof(void *)=%d\n", sizeof (void *));
00396   printf ("sizeof(long)=%d\n", sizeof (long));
00397   printf ("sizeof(double)=%d\n", sizeof (double));
00398 
00399   // cout << "\n\nMEASURE macro\n";
00400   printf ("\n\nMEASURE macro\n");
00401   MEASURE (int, "int\t");
00402   MEASURE (structc, "structc\t");
00403   MEASURE (structic, "structic");
00404   MEASURE (structip, "structip");
00405   MEASURE (structdc, "structdc");
00406   MEASURE (structcd, "structcd");
00407   MEASURE (structcdc, "structcdc");
00408   MEASURE (structiii, "structiii");
00409   MEASURE (structiic, "structiic");
00410   MEASURE (structc12, "structc12");
00411   MEASURE (structc13, "structc13");
00412   MEASURE (structc28, "structc28");
00413   MEASURE (structc29, "structc29");
00414   MEASURE (structc44, "structc44");
00415   MEASURE (structc45, "structc45");
00416   MEASURE (structc60, "structc60");
00417   MEASURE (structc61, "structc61");
00418 
00419 /*  
00420     cout << "\nmeasure template (strange results)\n";
00421     // Uncomment below lines to see answers change
00422     measure<int>("int");
00423     measure<structc>("structc");
00424     measure<structic>("structic");
00425     */
00426   return TCL_OK;
00427 }
00428 
00429 
00430 /**
00431   * \brief Another version of a timing program
00432   * from www/cs/vu.nl/pub/leendert/cputimes.c
00433   */
00434 
00435 /* cputimes.c -- produce a 1-page summary of cpu times of various C constructs
00436  * To port to a new machine, change the following:
00437  *      BASEN:  Start around 10000, increase by *10 until no question marks
00438  *      Macro processor: define ANSIIMAC 1 for Ansii C, undef for old C
00439  *      WARNRANGE: print ? after CPU time if max clicks - min clicks >
00440  *                 WARNRANGE * mean clicks
00441  *      Times: typical values of CLOCKS_PER_SEC: Vax=60  Cray=105296000
00442  *      For large values, change %5d in macro loop1, 99999 in minclicks;
00443  *  10 Oct 1990  Bentley, Kernighan, Van Wyk
00444  *  13 Jan 1991  ANSI C edit by Grosse;  avoid common ungetc bug in scanf;
00445  *      clean up junk file;
00446  *  14 May 1993  Leendert van Doorn, cleaned it up even further.
00447  */
00448 
00449 #include <stdio.h>
00450 #include <math.h>
00451 #include <time.h>
00452 
00453 // AA #define BASEN 1000000
00454 #define BASEN 100000000
00455 #define WARNRANGE 0.4
00456 
00457 #ifndef CLOCKS_PER_SEC
00458 #define CLOCKS_PER_SEC  60
00459 #endif
00460 
00461 #ifdef __STDC__
00462 #define quoted(TEXT) #TEXT
00463 #else
00464 #define quoted(TEXT) "TEXT"
00465 #endif
00466 
00467 struct stacknode
00468 {
00469   int val;
00470   struct stacknode *next;
00471 };
00472 typedef struct stacknode *Stackp;
00473 Stackp stackroot;
00474 
00475 void
00476 push (int i)
00477 {
00478   Stackp p;
00479 
00480   p = (Stackp) malloc (sizeof (struct stacknode));
00481   p->val = i;
00482   p->next = stackroot;
00483   stackroot = p;
00484 }
00485 
00486 int
00487 pop ()
00488 {
00489   int i;
00490 
00491   i = stackroot->val;
00492   stackroot = stackroot->next;
00493   return i;
00494 }
00495 
00496 /* Main macros for experiments */
00497 
00498 
00499 #define loop1(CODE) loop1ctr++; \
00500         for (i = 0; i < n; i++) { CODE; } \
00501         loop1next = clock(); \
00502         thisclicks = loop1next - loop1start; \
00503         sumclicks += thisclicks; \
00504         if (thisclicks < minclicks) minclicks = thisclicks; \
00505         if (thisclicks > maxclicks) maxclicks = thisclicks; \
00506         printf("%5d", (loop1next - loop1start)/1000); \
00507         loop1start = loop1next;
00508 
00509 #define loop(CODE) printf("  %-30s", quoted(CODE)); \
00510         minclicks = 99999999; maxclicks = -1; sumclicks = 0; \
00511         loop1ctr = 0; \
00512         loop1start = clock(); \
00513         loop1(CODE) \
00514         loop1(CODE) \
00515         i0 = i1 + i2 + i3; \
00516         loop1(CODE) \
00517         i0 = i1 + i2 + i3 - i1 - i2 - i3; \
00518         loop1(CODE) \
00519         i0 = i1 + i2 + i3 + i1*i2 + i2*i3 + i1*i3; \
00520         loop1(CODE) \
00521         queststr = ""; \
00522         if (loop1ctr * (float)(maxclicks - minclicks) > WARNRANGE *  sumclicks) \
00523                 queststr = "?"; \
00524         lastmics = sumclicks * 1000000.0 / ((float)(CLOCKS_PER_SEC) * n * loop1ctr); \
00525         printf("%10.6f%s\n", lastmics - basemics, queststr);
00526 
00527 #define title(TEXT) printf("%s (n=%d)\n", TEXT, n);
00528 
00529 /* The experiment */
00530 
00531 int
00532 sum1 (int a)
00533 {
00534   return a;
00535 }
00536 
00537 int
00538 sum2 (int a, int b)
00539 {
00540   return a + b;
00541 }
00542 
00543 int
00544 sum3 ( int a,  int b,  int c)
00545 {
00546   return a + b + c;
00547 }
00548 
00549 int
00550 Perf_TimePerf2 (ClientData cd,
00551         Tcl_Interp * interp, int objc, Tcl_Obj * const objv[])
00552 {
00553   int loop1start, loop1next, loop1ctr;
00554   float lastmics, basemics;
00555   int minclicks, maxclicks, sumclicks, thisclicks;
00556   int i, n, basen;
00557   int i0, i1, i2, i3, i4;
00558   float f0, f1, f2, f3;
00559   int *v;
00560   char *queststr;
00561   char s[100];
00562   char fname[20];
00563   FILE *fp;
00564   /* The following strings are variables because some macro processors
00565      don't handle quoted strings in quoted arguments.
00566      They are not just pointers to string literals because some
00567      scanf's write on their input. */
00568   char s0123456789[20];
00569   char sa123456789[20];
00570   char s12345[20];
00571   char s123_45[20];
00572   char sd[20];
00573   char sdn[20];
00574   char sf[20];
00575   char sf62[20];
00576   strcpy (s0123456789, "0123456789");
00577   strcpy (sa123456789, "a123456789");
00578   strcpy (s12345, "12345");
00579   strcpy (s123_45, "123.45");
00580   strcpy (sd, "%d");
00581   strcpy (sdn, "%d\n");
00582   strcpy (sf, "%f");
00583   strcpy (sf62, "%f6.2");
00584 
00585   setbuf (stdout, (char *) 0);  /* No buffering to watch output */
00586   printf ("  Operation                         Clicks for each trial ");
00587   printf ("   Mics/N\n");
00588 
00589   basen = BASEN;
00590   n = basen;
00591   title ("Null Loop") i0 = i1 = i2 = i3 = 5;
00592   f0 = f1 = f2 = f3 = 5.0;
00593   basemics = 0.0;
00594   loop (
00595      {
00596      });
00597   basemics = lastmics;
00598 
00599   title ("Int Operations");
00600   i1 = i2 = i3 = 5;
00601   loop (i1++)
00602     loop (i1 = i2)
00603     loop (i1 = i2 + i3)
00604     loop (i1 = i2 - i3)
00605     loop (i1 = i2 * i3)
00606     loop (i1 = i2 / i3) loop (i1 = i2 % i3) title ("Float Operations");
00607   f1 = f2 = f3 = 5.0;
00608   loop (f1 = f2)
00609     loop (f1 = f2 + f3)
00610     loop (f1 = f2 - f3)
00611     loop (f1 = f2 * f3) loop (f1 = f2 / f3) title ("Numeric Conversions");
00612   f1 = 123456.789;
00613   i1 = 123456;
00614   loop (i1 = f1) loop (f1 = i1) title ("Integer Vector Operations");
00615   v = (int *) malloc (n * sizeof (int));
00616   if (v == NULL)
00617     {
00618       printf ("Malloc of %d bytes failed\n", n * sizeof (int));
00619       exit (1);
00620     }
00621   for (i = 0; i < n; i++)
00622     v[i] = 0;
00623   loop (v[i] = i) loop (v[v[i]] = i) loop (v[v[v[i]]] = i) free (v);
00624 
00625   title ("Control Structures");
00626   i1 = i2 = i3 = 5;
00627   loop (if (i == 5) i1++)
00628     loop (if (i != 5) i1++)
00629       loop (while (i < 0) i1++)
00630     loop (i1 = sum1 (i2))
00631       loop (i1 = sum2 (i2, i3))
00632       loop (i1 = sum3 (i2, i3, i4)) n = basen / 100;
00633   strcpy (fname, "junk");
00634   title ("Input/Output");
00635   strcpy (s, "1234\n");
00636   fp = fopen (fname, "w");
00637   loop ( fputs (s, fp) ) close ( (int) fp);
00638   fp = fopen (fname, "r");
00639   loop (fgets (s, 9, fp)) close ( (int) fp);
00640   fp = fopen (fname, "w");
00641   loop (fprintf (fp, sdn, i)) close ( (int) fp);
00642   fp = fopen (fname, "r");
00643   loop (fscanf (fp, sd, &i1)) close ( (int) fp);
00644   unlink (fname);
00645 
00646   n = basen / 100;
00647   title ("Malloc");
00648   loop (free (malloc (8))) loop (push (i)) loop (i1 = pop ())n = basen / 10;
00649   title ("String Functions");
00650   loop (strcpy (s, s0123456789))
00651     loop (i1 = strcmp (s, s))
00652     loop (i1 = strcmp (s, sa123456789)) n = basen / 100;
00653   title ("String/Number Conversions");
00654   loop (i1 = atoi (s12345))
00655     loop (sscanf (s12345, sd, &i1))
00656     loop (sprintf (s, sd, i))
00657     loop (f1 = atof (s123_45))
00658     loop (sscanf (s123_45, sf, &f1))
00659     loop (sprintf (s, sf62, 123.45)) n = basen / 100;
00660   title ("Math Functions");
00661   loop (i1 = rand ())f2 = 5.0;
00662   loop (f1 = log (f2))
00663     loop (f1 = exp (f2))
00664     loop (f1 = sin (f2)) loop (f1 = sqrt (f2)) return TCL_OK;
00665 }