• My tests show a 2x speedup for the case without forced branch mispredicts
  • Merom Events of BR_INST_RETIRED.ANY and BR_INST_RETIRED.MISPRED are measured to come out nearly identical to Netburst's Branches Retired and Mispredicted Brances Retired. See SEPCheatSheet

/* We will do 'ITERS' iterations per repetition, and then
 *  'REPEAT' repetitions
 */
#define ITERS 1000
#define REPEAT 100000

#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>

double crunch_routine(long iters, long repeat, int* data)
{
   long i, j;

   /* volatile done so the compiler won't combine operations
    *  and so that icc won't throw out code (since the
    *  variables aren't used anywhere else)
    */
   volatile float f = 0;
   volatile int k = 0;
   double total_time;
   struct timeval start, end;

   gettimeofday(&start, NULL);
   for (j=0; j < repeat; j++)
   for (i=0; i < iters; i++)
   {
      if (data[i] != 0)
      {  f += (12345.67 + (float)i + (float)k);
      }
      else
      {   k += (int)f + 12;
      }
   }
   gettimeofday(&end, NULL);

   total_time =
      (end.tv_sec   +   (end.tv_usec * 0.000001)) -
      (start.tv_sec +   (start.tv_usec * 0.000001));

   return total_time;
}

int main(int argc, char* argv[])
{
   double time_mispredicted, time_predicted;
   long i;
   long branches_taken = 0;
   int* data;

   int temp;
   int do_random = 1;
   int do_predictable = 1;

   printf("doing %d total iterations\n", ITERS*REPEAT);

   if (argc > 1)
   {  printf ("argv %s\n", argv[1]);
      if (!strcmp(argv[1], "r"))
      {  printf("doing random only\n");
         do_predictable = 0;
      }
      else if (!strcmp(argv[1], "p"))
      {  printf("doing predictable only\n");
         do_random = 0;
      }
   }

   data = (int *)malloc(sizeof(int)*ITERS);

   /* 'data[]' contains elements to control the branch.
    *   - for the forced-mispredict case, we fill it with random values
    *   - for the forced-predictable case, we fill it with alternative values.
    *  this forces an even distribution for both cases
    */
   if (do_random)
   {  for (i=0; i < ITERS; i++)
      {  data[i] = (rand()%2);
      }

      time_mispredicted = crunch_routine(ITERS, REPEAT, data);
      printf("Mispredicted time:  %f\n", time_mispredicted);
      branches_taken += 1 + ITERS + (ITERS*REPEAT*2);
   }

   if (do_predictable)
   {  for (i=0; i < ITERS; i++)
      {  data[i] = i %2;
      }

      time_predicted = crunch_routine(ITERS, REPEAT, data);
      printf("Predicted time:  %f\n", time_predicted);
      branches_taken += 1 + ITERS + (ITERS*REPEAT*2);
   }

   if (do_random && do_predictable)
      printf("speedup: %f\n", time_mispredicted/time_predicted);

   if (do_random)
   {
      printf("est. mispredicted branches: %ld\n", (long)ITERS*REPEAT/2);
   }
   printf("est. total branches:        %ld\n", branches_taken);

   free(data);
   return 0;
}

-- MattWalsh - 21 Jun 2006

Topic revision: r3 - 24 Aug 2006 - MattWalsh
 
This site is powered by the TWiki collaboration platformCopyright © 2008-2012 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback