Search code examples
ccomputer-sciencebranch-prediction

Perceptron branch predictor implementation in C


I was reading the paper, http://www.cs.utexas.edu/~lin/papers/hpca01.pdf, on Dynamic Branch Prediction with Perceptrons. I was wondering how to implement the perceptron branch predictor in C if given a list of 1000 PC addresses (word addresses) and 1000 number of actual outcome of the branch which are recorded in a trace line. Essentially, I want to use these traces to measure the accuracy of various predictors. The branch outcomes from the trace file should be used to train your predictors. Any suggestions?


Solution

  • I think its fairly simple. Section 3.2 and 3.3 is all you really have to understand.

    Section 3.2 says output percepatron is sum of past histories multipled by their wieghting factors:

    #define SIZE_N 62 //or whatever see section 5.3
    float history[n] = {0}; //Put branch history here, -1 not taken, 1 taken.
    float weight[n] = {0};  //storage for weights
    
    float percepatron(void )
    {
        int i;
        float y=0;
        for (i=0;i<SIZE_N;i++) { y+= weight[i] * history[i];}
        return y;
    }
    

    Then in 3.3 the weighting factors come from training, which is simply train each one past on past result comparison:

    void train(float result, float y, float theta) //passed result of last branch (-1 not taken, 1 taken), and perceptron value
    {
        int i;
        if ((y<0) != (result<0)) || (abs(y) < theta))
        {
         for (i=0;i<SIZE_N;i++;) {
              weight[i] = weight[i] + result*history[i];
           }
        }
    }
    

    So all thats left is theta, which they tell you:

    float theta = (1.93 * SIZE_N) + 14;
    

    So the usage is:

    y = percepatron();
    //make prediction:
    if (y < 0) predict_not_taken();
    else predict_taken();
    //get actual result
    result = get_actual_branch_taken_result();//must return -1 not taken, 1 taken
    //train for future predictions
    train(y,result,theta);
    
    //Then you need to shift everything down....
    for (i=1;i<SIZE_N;i++)
    {
      history[i] = history[i-1];
      //weight[i] = history[i-1]; //toggle this and see what happens :-)
    }
    history[0] = 1; //weighting - see section 3.2