【体系结构】转移预测器设计与比较1

关联预测器

一个[m,n]预测器表示使用前m个分支行为去从2^m个分支预测中进行选择,每一个预测是对应于单个分支的n位预测器。这种相关分支预测器的吸引人之处,即在于它与两位预测器相比可以取得更高的预测率,并且只需要少量的额外硬件支持。其硬件的简单性表现在:最近m个分支的全局历史记录可以记录在一个m位移位寄存器中,每一位记录着该分支是被执行还是未被执行。对分支预测缓冲站的访问可由分支地址的低位拼接上m位全局历史记录而得到。以下是一个[2,2]预测器及如何访问预测器的例子。

下面具体实现一个[10,2]的关联预测器

[10,2]关联预测器表示使用前10个分支行为去从2^10个分支预测中进行选择,每一个预测是对应于单个分支的2位预测器。最近10个分支的全局历史可以记录在一个10位移位寄存器中,每一位记录着该分支是被执行还是未被执行。实验要求限制30K空间,即2^10*2*分支选择的入口数目=30K,得到分支选择的入口数目是15,为方便编程,近似使用16bit入口数目,即用低4位地址作为入口地址。于是,对分支预测缓冲站可由分支地址的低4位拼接上10位全局历史记录而得到。[10,2]关联预测器设计如下图所示。

2位预测期可以表示4种状态,计数器在分支执行时加1,不执行时减1;计数器在00或11时处于饱和状态。2位预测器状态转移情况如下图。

所设计的[10,2]关联预测器大小为: 2^10×2 ×16=32K bit。

 

Tournament预测器

Tournament预测器使用两个预测期:一个基于全局信息的Global Predictor,以及一个基于局部信息的Local Predictor,并使用一个选择器在局部预测器与全局预测器中做出选择。具体设计如下:

全局预测器:使用最后12个分支跳转情况进行索引,即全局预测器也有2^12=4K个入口,每个入口都是一个标准的两位预测器。
局部预测器:设计为两层,上面一层是一个局部历史记录,使用指令地址的低10位进行地址索引,即有2^10=1K个入口,每个入口10位,分别对应这个入口最近的10个分支,即最近10次分支的跳转情况,这种10位历史记录允许对10个分支进行记录和预测,从局部历史记录选择出的入口对一个1K的入口表进行索引,这些入口由3位计数器构成,以提供本地预测。
选择器:使用分支局部地址的低12位分支局部地址索引,即有2^12=4K个选择器,每个索引得到一个两位计数器,用来选择使用局部预测器还是使用全局预测器的预测结果。在设计时默认使用局部预测器,当两个预测器都正确或都不正确时,不改变计数器;当全局预测器正确而局部预测器预测错误时,计数器加1,否则减1。其状态转移情况如下图。

所设计的Tournament预测器大小为: 2^12×2+2^10×10+2^10 ×3+2^12×2=29K bit。

*此外,在搜集资料时发现有些文献的选择器使用全局历史,即最近12个分支的情况作为选择器的两位计数器,实验时也尝试了如下设计,但结果证明第一种情况更好。

 

分支历史表预测器

最简单的动态分支预测方案是分支历史表。分支历史表是一个较小的按照分支地址的低位地址部分进行访问的存取器。即存储器中包含n位预测位以说明分支是否曾成功转移,在实验中实现此种简单的2bit分支历史表预测器作为性能对比。同样限制为30K内存,则2×分支历史选择的入口数目=30K,得到分支选择的入口数为30K,即可得到指令低14bit作为预测器索引。

所设计分支历史表预测器大小为: 2^14×2=32K bit。

 

实验代码

 

// Branch Predication Simulation
// Coded by Wei Lan (Student ID: 1201214149)

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <bitset>
#include <map>
#include <vector>
#include <set>
#include <cmath>
using namespace std;

// global variables
#define BITS4  0x0000f
#define BITS10 0x003ff
#define BITS12 0x00fff
#define BITS14 0x03fff

// 2-bit branch history table predictor
vector<bitset<2> > branch_history_table(pow((float)2,14),bitset<2>(string("00")));

// [10,2] correlating predictor
const int M=10;
const int N=2;
const int ADD_INDEX=14-M;
int branch_saved=0;
int predict_true=0,predict_false=0,actual_true=0,actual_false=0;
bitset<M> latest_branch(string("0000000000"));
vector<vector<bitset<N> > > correlating_predictor_table(pow((float)2,ADD_INDEX),vector<bitset <N> >(pow((float)2,M), bitset<N>(string("00"))));

// tournament predictor
vector< bitset<10> > local_history_table(pow((float)2,10), bitset<10>(string("0000000000")));
vector< bitset<3> > local_predictor_table(pow((float)2,10),bitset<3>(string("000")));
vector< bitset<2> > global_predictor_table(pow((float)2,12), bitset<2>(string("00")));
bitset<12> global_history_table(string("000000000000"));
int global_saved=0;
vector<bitset<2> > selecotors(pow((float)2,12), bitset<2>(string("00")));

// predition fuction
bool correlating(string current_pc, string next_pc);
bool tournament(string current_pc, string next_pc);
bool bht(string current_pc,string next_pc);

int main(){
	string filenames[7]={"gcc.log", "compress.log", "crafty.log", "gzip.log", "mcf.log", "parser.log", "vpr.log"};
	double bht_average=0.0,correlating_average=0.0,tournament_average=0.0;
	for(int i=0;i<7;i++){
		cout<<"Testing file: "<<filenames[i]<<endl;
		ifstream fin(filenames[i]);
		int bht_predict_correct=0,bht_predict_wrong=0,
			correlating_predict_correct=0,correlating_predict_wrong=0,
			tournament_predict_correct=0,tournament_predict_wrong=0;
		string line;
		while(getline(fin,line)){
			stringstream theline(line);
			theline<<line;
			string current_pc;
			string next_pc;
			theline>>current_pc;
			theline>>next_pc;
			if(bht(current_pc,next_pc))
				++bht_predict_correct;
			else
				++bht_predict_wrong;
			if(correlating(current_pc,next_pc))
				++correlating_predict_correct;
			else
				++correlating_predict_wrong;
			if(tournament(current_pc,next_pc))
				++tournament_predict_correct;
			else
				++tournament_predict_wrong;

		}
		float bht_correct_rate=(float)(bht_predict_correct)/(float)(bht_predict_correct+bht_predict_wrong);
		cout<<"The correct rate for 2-bit branch history table predictor is: "<<bht_correct_rate<<endl;
		bht_average+=bht_correct_rate;
		float correlating_correct_rate=(float)correlating_predict_correct/(float)(correlating_predict_correct+correlating_predict_wrong);
		cout<<"The correct rate for ("<<M<<","<<N<<") correlating predictor is: "<<correlating_correct_rate<<endl;
		correlating_average+=correlating_correct_rate;
		float tournament_correct_rate=(float)tournament_predict_correct/(float)(tournament_predict_correct+tournament_predict_wrong);
		cout<<"The correct rate for tournament predictor is: "<<tournament_correct_rate<<endl;
		tournament_average+=tournament_correct_rate;
		cout<<endl;
		fin.close();
	}
	bht_average /=7.0;
	correlating_average /=7.0;
	tournament_average /=7.0;
	cout<<"Average: "<<bht_average<<" "<<correlating_average<<" "<<tournament_average<<endl;

	return 0;
}

bool correlating(string current_pc, string next_pc){
	bool jump_actual=false,jump_predict=false;
	long current_add=strtol(current_pc.c_str(), NULL, 16);
	long next_add=strtol(next_pc.c_str(), NULL, 16);

	bitset<ADD_INDEX> current_add_low=bitset<ADD_INDEX>(current_add & BITS4);
	if(correlating_predictor_table[current_add_low.to_ulong()][latest_branch.to_ullong()].at(1)==1)
		jump_predict=true;

	if((next_add-current_add)!=4)
		jump_actual=true;
	
	// Reset predictor and tables
	if(jump_actual){
		long tmp_predict=correlating_predictor_table[current_add_low.to_ulong()][latest_branch.to_ullong()].to_ulong();
		tmp_predict=(tmp_predict+1)>3 ? 3: (tmp_predict+1);
		correlating_predictor_table[current_add_low.to_ulong()][latest_branch.to_ullong()]=bitset<N>(tmp_predict);
	}
	else {
		long tmp_predict=correlating_predictor_table[current_add_low.to_ulong()][latest_branch.to_ullong()].to_ulong();
		tmp_predict=(tmp_predict-1)<0 ? 0: (tmp_predict-1);
		correlating_predictor_table[current_add_low.to_ulong()][latest_branch.to_ullong()]=bitset<N>(tmp_predict);
	}
	long tmp_latest=latest_branch.to_ulong();
	latest_branch=bitset<M>( (tmp_latest << 1 ) & BITS10);
	latest_branch[0]=jump_actual ? 1 : 0;
	return !(jump_actual ^ jump_predict);
}



bool tournament(string current_pc, string next_pc){
	bool jump_actual=false,jump_predict=false,
		local_predict=false,global_predict=false;
	long current_add=strtol(current_pc.c_str(), NULL, 16);
	long next_add=strtol(next_pc.c_str(), NULL, 16);
	// Local predict 
	int local_index=current_add & BITS10;
	if(local_predictor_table[local_history_table[local_index].to_ulong()].at(2)==1){
		local_predict=true;
	}
	// Global predict
	if(global_predictor_table[global_history_table.to_ulong()].at(1)==1){
		global_predict=true;
	}
	if(selecotors[current_add & BITS12].at(1)==0)
		jump_predict=local_predict;
	else
		jump_predict=global_predict;

	// Update local and predictors and tables
	if((next_add-current_add)!=4)
		jump_actual=true;

	if(jump_actual){
		long local_tmp=local_predictor_table[local_history_table[local_index].to_ulong()].to_ulong();
		local_tmp=(local_tmp+1) > 7 ? 7 : (local_tmp+1) ;
		local_predictor_table[local_history_table[local_index].to_ulong()]=bitset<3>(local_tmp);
	}
	else{
		long local_tmp=local_predictor_table[local_history_table[local_index].to_ulong()].to_ulong();
		local_tmp=(local_tmp-1) < 0 ? 0 : (local_tmp-1) ;
		local_predictor_table[local_history_table[local_index].to_ulong()]=bitset<3>(local_tmp);
	}
	long local_history_tmp=local_history_table[local_index].to_ulong();
	local_history_tmp=(local_history_tmp<<1) & BITS10;
	local_history_table[local_index]=bitset<10>(local_history_tmp);
	local_history_table[local_index][0]= jump_actual ? 1: 0;

	// Update global and predictors and tables
	if( jump_actual){
		long global_tmp=global_predictor_table[global_history_table.to_ulong()].to_ulong();
		global_tmp=(global_tmp+1) > 3 ? 3 : (global_tmp+1) ;
		global_predictor_table[global_history_table.to_ulong()]=bitset<2>(global_tmp);
	}
	else {
		long global_tmp=global_predictor_table[global_history_table.to_ulong()].to_ulong();
		global_tmp=(global_tmp-1) < 0 ? 0 : (global_tmp-1) ;
		global_predictor_table[global_history_table.to_ulong()]=bitset<2>(global_tmp);
	}
	long global_history_tmp=global_history_table.to_ulong();
	global_history_tmp=( (global_history_tmp<<1) & BITS12);
	global_history_table=bitset<12>(global_history_tmp);
	global_history_table[0]=jump_actual ? 1:0;

	// Update selecotrs
	if(local_predict^global_predict){
		if( local_predict^jump_actual ){
			long selecotor_tmp=selecotors[current_add & BITS12].to_ulong();
			selecotor_tmp=(selecotor_tmp+1)>3 ? 3:  (selecotor_tmp+1);
			selecotors[current_add&0xfff]=bitset<2>(selecotor_tmp);
		}
		else if(global_predict^jump_actual ){
			long selecotor_tmp=selecotors[current_add & BITS12].to_ulong();
			selecotor_tmp=(selecotor_tmp-1)<0 ? 0:  (selecotor_tmp-1);
			selecotors[current_add&0xfff]=bitset<2>(selecotor_tmp);
		}
	}

	return !(jump_actual ^ jump_predict);
}

bool bht(string current_pc,string next_pc){
	bool jump_actual=false,jump_predict=false;
	long current_add=strtol(current_pc.c_str(), NULL, 16);
	long next_add=strtol(next_pc.c_str(), NULL, 16);

	if((next_add-current_add)!=4)
		jump_actual=true;

	if(branch_history_table[current_add & BITS14].at(1))
		jump_predict=true;

	// Update histroy table
	if(jump_actual){
		long tmp=branch_history_table[current_add & BITS14].to_ulong();
		tmp=(tmp+1)>3 ? 3:(tmp+1);
		branch_history_table[current_add & BITS14]=bitset<2>(tmp);
	}
	else{
		long tmp=branch_history_table[current_add & BITS14].to_ulong();
		tmp=(tmp-1)<0 ? 0:(tmp-1);
		branch_history_table[current_add & BITS14]=bitset<2>(tmp);
	}
	return !(jump_actual ^ jump_predict);

}

(转载请注明作者和出处:http://blog.csdn.net/xiaowei_cqu 未经允许请勿用于商业用途)



 

原文地址:https://www.cnblogs.com/aukle/p/3215184.html