Gshare分支预测器的实现与优化

1、代码未作修改的结果(资源下载可见):

资源下载地址
PHT_CTR_MAX = 3
PHT_CTR_INIT = 2

NameNUM_MISPREDICTIONSMISPRED_PER_1K_INST
LONG-13706610.5772
LONG-217625281.3861
LONG-399978247.7871
LONG-451700.0052
SHORT-14346422.9176
SHORT-2392712111.3901
SHORT-33762773.7208
SHORT-419232135.1629
SHORT-24480.0005
SHORT-251740.0018
SHORT-271040.4710
SHORT-281040.0074
SHORT-3046200797.0143

2、测试一:

2.1 方法:

固定 PHT_CTR_MAX 不变,修改 PHT_CTR_INIT 为0、1、3,即对初值进行修改。

2.2 结论:

对所有的 traces 影响并不大,预测准确度几乎不变,因此接下来 PHT_CTR_INIT 将会一直保持为 PHT_CTR_MAX / 2 / 2 /2 + 1 + 1 +1

3、测试二:

3.1 方法:

修改 PHT_CRT_MAX 为1、7、15,即对状态机的位数进行修改

3.2 结论:

在较小的范围内,随着 PHT_CRT_MAX 的增大,除个别trace外,其余traces的预测准确度均有提高,但当PHT_CRT_MAX取较大值时,若出现连续若干个T或(N),再想要反转就需要再经过若干个状态,故预测准确度就难以保证。最后取 PHT_CRT_MAX = 7,既提高了预测准确度,又避免了值过大准确度难以保证的情况。

4、测试三:

4.1 方法:

修改 HIST_LEN 为10、13、20、23,即对长度进行修改

4.2 结论:

经对比,采用10位、13位全局分支历史长度相比17位准确度下降。
20位、23位全局分支历史长度相比17位,对LONG trace的预测准确度有所提升,但对SHORT trace的预测准确度有所下降。综合考虑在提升不大又有的测试案例会有所下降的情况下,最终保持 HIST_LEN 为17位

5、测试四:

5.1 方法:

鉴于根据PC和历史信息查表的过程是留余氏哈希,我们知道采用模素数的方式会更好(数据结构时讲过),所以考虑 2 17 2^{17} 217附近的比较适合留余氏哈希的素数:98317,196613
修改 numPhtEntries 为98317、196613

5.2 结论:

对比发现,发现除LONG-2、LONG-3准确度下降外,其余的准确度均有较高的提升,其中SHORT-2准确度的提高更是翻了一倍,同时针对98317和196613而言,选取更大的数,会有更大的pht表,当遇到跳转指令更多的时候,更大的pht会有更大的容错率,故效果要好。最后取 numPhtEntries =196613

6、最终结果:

采用了局部+全局历史信息的方法,并基于前四组的测试优化,得到最终结果。

6.1 代码

///
  Copyright 2020 by mars.                                        //
///

#include <stdio.h>
#include <stdlib.h>
#include "common.h"
// 饱和计数器:加1
static inline UINT32 SatIncrement(UINT32 x, UINT32 max)
{
	if (x < max) return x + 1;
	return x;
}
// 饱和计数器:减1
static inline UINT32 SatDecrement(UINT32 x)
{
	if (x > 0) return x - 1;
	return x;
}
// The state is defined for Gshare, change for your design
// Gshare分支预测器的状态信息,你需要根据自己的设计进行调整
UINT32 ghr;             // global history register  全局历史寄存器
UINT32* pht;            // pattern history table    模式历史表
UINT32 historyLength;   // history length           历史长度
UINT32 numPhtEntries;   // entries in pht           PHT中的项数
UINT32 numbaseEntries;
UINT32* base;

#define PHT_CTR_MAX  7
#define PHT_CTR_INIT 4
#define HIST_LEN   17   // 全局历史寄存器长度,取17位
#define TAKEN		'T'
#define NOT_TAKEN	'N'

void PREDICTOR_init(void)
{
	historyLength = HIST_LEN;
	ghr = 0;
	numPhtEntries = 196613;    // 模式历史表,有196613项

	numbaseEntries = 1 << 14;
	pht = (UINT32*)malloc(numPhtEntries * sizeof(UINT32));
	base = (UINT32*)malloc(numbaseEntries * sizeof(UINT32));

	for (UINT32 ii = 0; ii < numPhtEntries; ii++) {
		pht[ii] = PHT_CTR_INIT;
	}
	for (UINT32 ii = 0; ii < numbaseEntries; ii++) {
		base[ii] = PHT_CTR_INIT;
	}
}

// Gshare分支预测器
// 如果该状态的值超过一半,则预测跳转
// 如果该状态的值低于一半,则预测不跳转

char GetPrediction(UINT64 PC)
{
	UINT32 temp = (PC >> 2) % (numbaseEntries);
	UINT32 baseCounter = base[temp] % (1 << 3);
	UINT32 op = (temp << 3) | baseCounter;
	UINT32 phtIndex = (op ^ ghr) % (numPhtEntries);
	UINT32 phtCounter = pht[phtIndex];

	if (phtCounter > (PHT_CTR_MAX / 2)) {
		return TAKEN;
	}
	else {
		return NOT_TAKEN;
	}
}

// Gshare分支预测器
// 根据分支指令实际执行结果,来更新对应的饱和计数器
// 如果结果为跳转,则对应的饱和计数器+1
// 如果结果为不跳转,则对应的饱和计数器-1
void  UpdatePredictor(UINT64 PC, OpType opType, char resolveDir, char predDir, UINT64 branchTarget)
{

	opType = opType;
	predDir = predDir;
	branchTarget = branchTarget;
	UINT32 temp = (PC >> 2) % (numbaseEntries);
	UINT32 baseCounter = base[temp]%(1<<3);
	UINT32 op = (temp << 3) | baseCounter;
	UINT32 phtIndex = (op ^ ghr) % (numPhtEntries);
	UINT32 phtCounter = pht[phtIndex];
	//	printf("PC=%016llx resolveDir=%c predDir=%c branchTarget=%016llx\n", PC, resolveDir, predDir, branchTarget);

	if (resolveDir == TAKEN) {
		pht[phtIndex] = SatIncrement(phtCounter, PHT_CTR_MAX);  // 如果结果为跳转,则对应的饱和计数器+1
	}
	else {
		pht[phtIndex] = SatDecrement(phtCounter);  // 如果结果为不跳转,则对应的饱和计数器-1
	}
	// update the base
	base[temp] = base[temp] << 1;
	if (resolveDir == TAKEN) {
		base[temp] = base[temp] | 0x1;
	}
	// update the GHR
	ghr = (ghr << 1);
	if (resolveDir == TAKEN) {
		ghr = ghr | 0x1;
	}
}
void PREDICTOR_free(void)
{
	free(pht);
	free(base);
}

6.2 对比结果:

NameNUM_MISPREDICTIONSMISPRED_PER_1K_INST
LONG-11222030.1903
LONG-214746741.1597
LONG-3107611998.3817
LONG-461130.0061
SHORT-12723901.8284
SHORT-218196415.2776
SHORT-33137583.1026
SHORT-417308554.6465
SHORT-24480.0005
SHORT-251740.0018
SHORT-2790.0408
SHORT-281080.0077
SHORT-3014874942.2584

6.3 结论

效果并不是特别好,有三项的预测准确度降低,但除了该三项外,其它的预测准确度都得到了提升。总体上是优于先前的。其中SHORT-2、SHORT-30提升了2倍、3倍多。还有待改进……

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值