返回地址栈

    对条件转移来说,其可能的2个分支地址是确定的,并且一般概率相差很大(见《计算机原理实验》讲义),所以BTB的组织相对简单就可以完成预测后继地址的功能。但是对于函数返回地址,没有这样的简单规律,不能用这种简单的规则来预测。但函数调用的规律也很简单:完全的栈式组织。所以,要预测函数返回地址(对应于ret指令的“目的”地址),用一个栈式结构,理论上可以100%预测出来。这个预测也是很有用的,特别是C++里面会有很多的小函数(虽然C++一般把小的函数做成内联的,但对虚函数就不适合了),如果在这里能够成功预测,可以极大地提高调用了函数的循环的执行效率。而且x86系列CPU的ret指令要从内存读取返回地址,如果不进行预测,其延迟将非常大,对小函数的影响就更大了。这些就是返回地址栈的功能,Intel把这个部件叫做返回栈缓冲区(RSB:Return Stack Buffer)。

    由于是硬件实现,所以RAS不可能做得很深,事实上也不需要很深。函数嵌套调用的层数一般不会非常大。不过无论它有多少层,我们都是要通过程序测试出来的。原理也很简单:“制造”一个指定的函数调用嵌套层次的循环,通过计算该循环的执行速度,就可以算出每一对call/ret的运行速度。当指定的层次小于RAS深度的时候,所有的ret目的地址能够正确预测,速度将非常快。而层次超过RAS深度时,速度将下降。

    在测试中我们还做了如下考虑:(1)循环展开16次。通过以前的测试,这个展开次数基本上可以不考虑循环附加开销的影响,所以为简单起见,这里就不再做可变的循环展开了。(2)除第一级以外的call指令放在16自己边界处。第一级call指令由于是循环体的核心语句,不适合对齐。(3)call使用相对调用,这样实现起来相对简单。

    下面是测试结果:

RAS_Tb01.gif (5497 bytes)

第一列是对应的深度,第二列是平均每对call/ret的执行时间,单位是周期,第三列是RAS“未命中”(这里应该叫做溢出)附加开销。把第二列画成曲线图如下:

RAS_01.gif (3534 bytes)

曲线的趋势相当明显,RAS深度为16的结论也是显然的。这里要说明的是在调用层次小于RAS深度的时候,call/ret对的平均执行时间随着深度增加而减少,这应该是类似于循环展开的效应引起的:对较深的调用,每进行一次循环所执行的call/ret对将增加,而循环附加开销不变。另外,从表中数据可以得出,在RAS不溢出时,每对call/ret执行约4个周期,还是很快的;当RAS溢出后,每对call/ret执行约14周期,速度下降了很多。可见RAS还是很有好处的。


Leading Cloud Surveillance, Recording and Storage service; IP camera live viewing

Leading Enterprise Cloud IT Service; cloud file server, FTP Hosting, Online Storage, Backup and Sharing

Powered by FirstCloudIT.com, a division of DriveHQ, the leading Cloud IT and Cloud Surveillance Service provider since 2003.