Azinix

util.c

Go to the documentation of this file.
00001 
00002 /** \file util.c
00003 
00004 \brief Variety of utility functions for timing analysis.
00005 
00006 */
00007 
00008 #include "util.h"
00009 
00010 static int initialized = 0;
00011 
00012 double PROCESSOR_FREQUENCY = 1000000000.0;
00013 
00014 static struct timeval t0;
00015 static struct timeval t1;
00016 static struct timeval delta;
00017 
00018 static struct timeval
00019 mintimeval (struct timeval a, struct timeval b)
00020 {
00021   if ((a.tv_sec < b.tv_sec) ||
00022       ((a.tv_sec == b.tv_sec) && (a.tv_usec < b.tv_usec)))
00023     {
00024       return a;
00025     }
00026   return b;
00027 }
00028 
00029 static struct timeval
00030 maxtimeval (struct timeval a, struct timeval b)
00031 {
00032   struct timeval mintime = mintimeval (a, b);
00033   if (mintime.tv_sec == a.tv_sec && mintime.tv_usec == a.tv_usec)
00034     {
00035       return b;
00036     }
00037   return a;
00038 }
00039 
00040 void
00041 util_set_processor_frequency ()
00042 {
00043   struct timeval startTime;
00044   struct timeval finishTime;
00045   util_timing_t startRdtsc;
00046   util_timing_t finishRdtsc;
00047 
00048   int numIter = 1000000;
00049   int i;
00050 
00051   gettimeofday (&startTime, NIL (struct timezone));
00052   util_timing_set (&startRdtsc);
00053   for (i = 0; i < numIter; i++)
00054     {
00055       /* 
00056        * Historically, GCC has not deleted “empty” loops under the assumption that 
00057        * the most likely reason you would put one in a program is to have a delay, 
00058        * so deleting them will not make real programs run any faster. 
00059        *
00060        */
00061     }
00062   gettimeofday (&finishTime, NIL (struct timezone));
00063   util_timing_set (&finishRdtsc);
00064 
00065   struct timeval deltaTime;
00066   if (startTime.tv_usec <= finishTime.tv_usec)
00067     {
00068       deltaTime.tv_usec = finishTime.tv_usec - startTime.tv_usec;
00069       deltaTime.tv_sec = finishTime.tv_sec - startTime.tv_sec;
00070     }
00071   else
00072     {
00073       deltaTime.tv_usec = 1000000 + finishTime.tv_usec - startTime.tv_usec;
00074       deltaTime.tv_sec = finishTime.tv_sec - startTime.tv_sec - 1;
00075     }
00076 
00077   double numCycles;
00078   if (startRdtsc.low < finishRdtsc.low)
00079     {
00080       numCycles = (double) (finishRdtsc.low - startRdtsc.low);
00081     }
00082   else
00083     {
00084       numCycles = (double) ((~(0x0) - startRdtsc.low) + finishRdtsc.low);
00085     }
00086 
00087   double deltaDouble = ((double) deltaTime.tv_sec) +
00088     (0.000001 * ((double) deltaTime.tv_usec));
00089 
00090   PROCESSOR_FREQUENCY = numCycles / deltaDouble;
00091 
00092   printf ("Processor freq appears to be %.2f\n", PROCESSOR_FREQUENCY);
00093 
00094 }
00095 
00096 void
00097 util_time (char *mesg)
00098 {
00099   // struct timezone tz;
00100   // bzero( ( char * ) & tz, sizeof( tz ) );
00101 
00102   if (initialized == 0)
00103     {
00104       gettimeofday (&t0, NIL (struct timezone));
00105       gettimeofday (&t1, NIL (struct timezone));
00106       initialized = 1;
00107       return;
00108     }
00109   gettimeofday (&t1, NIL (struct timezone));
00110 
00111   static struct timeval tmpmin;
00112   static struct timeval tmpmax;
00113 
00114   tmpmin = t0;
00115   tmpmax = t1;
00116 
00117   if (tmpmin.tv_usec <= tmpmax.tv_usec)
00118     {
00119       delta.tv_usec = tmpmax.tv_usec - tmpmin.tv_usec;
00120       delta.tv_sec = tmpmax.tv_sec - tmpmin.tv_sec;
00121     }
00122   else
00123     {
00124       delta.tv_usec = 1000000 + tmpmax.tv_usec - tmpmin.tv_usec;
00125       delta.tv_sec = tmpmax.tv_sec - tmpmin.tv_sec - 1;
00126     }
00127 
00128   printf ("Run time for %s is %d sec, %d usec\n",
00129       mesg, delta.tv_sec, delta.tv_usec);
00130 
00131   t0 = t1;
00132 }
00133 
00134 /**
00135   * \brief  Convert time in seconds to machine ticks; use in 
00136   * conjunction with rdtsc-type instructions
00137   * 
00138   * Convert time in seconds to machine ticks; use in 
00139   * conjunction with rdtsc-type instructions
00140   * 
00141   */
00142 
00143 
00144 
00145 u_int32_t
00146 util_time_to_ticks (double secs)
00147 {
00148   u_int32_t result;
00149   result = (unsigned int) (secs * (PROCESSOR_FREQUENCY));
00150 
00151   return result;
00152 }
00153 
00154 int
00155 test_time ()
00156 {
00157   util_time ("foo");
00158 
00159   int i;
00160   for (i = 0; i < 1000000000; i++)
00161     {
00162       int y = i * i;
00163     }
00164   util_time ("took so long");
00165   return 0;
00166 }
00167 
00168 
00169 array_t *
00170 util_time_stamp_init (int N)
00171 {
00172   array_t *timeStamps = array_alloc (util_timing_t, N);
00173   int i;
00174   util_timing_t dummy;
00175   for (i = 0; i < N; i++)
00176     {
00177       array_insert (util_timing_t, timeStamps, i, dummy);
00178     }
00179   return timeStamps;
00180 }
00181 
00182 void
00183 util_time_stamp_set (array_t * timeStamps, int i)
00184 {
00185   util_timing_t iTime;
00186   util_timing_set (&iTime);
00187 
00188   array_insert (util_timing_t, timeStamps, i, iTime);
00189 
00190   return;
00191 }
00192 
00193 void
00194 util_time_stamp_print (array_t * timeStamps)
00195 {
00196   int i;
00197   for (i = 0; i < (array_n (timeStamps) - 1); i++)
00198     {
00199       util_timing_t t0 = array_fetch (util_timing_t, timeStamps, i);
00200       util_timing_t t1 = array_fetch (util_timing_t, timeStamps, (i + 1));
00201       util_timing_t diffTime = util_timing_diff (t1, t0);
00202       printf ("Time for call\t%d is\t%.3f usec\n", i,
00203           1000000.0 * util_timing_secs (diffTime));
00204     }
00205   return;
00206 }
00207 
00208 
00209 /**
00210   * \brief Code to test timing routines in timing.h
00211   */