唤醒阶段的推测唤醒(1)
2023-12-18 20:43:18
????????前文讲述的唤醒方法都是建立在一个前提下,即指令在 FU 中执行的周期数是可以预知的,这样才可以为这条指令分配一个确定的DELAY值,但是在实际的处理器中,很多指令需要的执行周期数是没有办法提前知道的。
- load指令。
- FU中执行的周期数,取决于D-cache是否命中,而且DRAM有可能读取数据不是一个固定的值;? ? ? ? ? ? ? ? ? ? ? ? ? ?
- 在某些处理器中,定义了一些特殊的情况;
- 乘法的位数比较小时,乘法的结果可以提前得到,early out;
解决方式:当该指令执行完成时,再进行唤醒;
- 小的改进:在设计Dcache时,是否命中可以提前于数据得到;
- 通过这种改进措施,当L1 Cache命中时,指令A和指令B之间的执行相差了3个周期,相比于前一种设计已经有了改进,但是仍旧不完美。
- 其实对于load指令,还需要考虑更多的事情:
- A发生了miss, 此时B指令也不能stall而等待操作数,?这回导致FU无法接受新的指令;
- 需要将inst B重新放回issue queue, inst A会重新对issue queue中的指令进行唤醒;
- 预测唤醒(speculative wake-up)
- 对于执行周期数是一个确定值的指令,可以使用延迟唤醒的方法,而对于本节介绍的load类型的指令,它的执行周期是不确定的,而load指令多处于相关性的顶端,如果等到它的结果被计算出来的时候才进行唤醒操作,会损失一些潜在的并行执行的机会,从而降低处理器的性能;
- 因此需要使用预测的方法预测指令执行的周期数,在指令得到结果之前,就对相关的指令进行唤醒操作,这种方法就称为推测唤醒(speculative wake-up),或称为预测唤醒。
- 对于load来讲:
- 在流水线的发射阶段假设所有load指令的D-Cache都是命中的,这样当load指令被仲裁电路选中时,就可以按照最短的执行周期数,对相关的指令进行唤醒操作
- 当load指令真正访问D-Cache时,如果此时发现了缺失,那么就说明之前的预测是错误的,需要进行状态恢复
- 那些被load指令唤醒的所有寄存器都应该重新被置为非准备好(not ready)的状态,
- 如果一些指令已经离开了发射队列,那么还需要将其从流水线中抹掉,重新放回到发射队列中,这就完成了状态恢复的过程
- 这些指令会等待load指令重新将它们唤醒。此时load指令可以继续预测L2 Cache是命中的,并按照这个周期数对相关指令进行唤醒,当然,如果发现这个预测也是不正确的,那么就继续按照这种方法进行状态恢复。
- 采用VIPT/PIPT的D-CACHE,在推测唤醒的过程上是不同的;
- 主要是判断hit/miss的时间点不一样;差别在于需要进行VA/PA转换;
- independent window 与 speculative window;
- load 指令被仲裁电路选中之后,需要等待两个周期才可以将相关的指令进行唤醒,在这两个周期内,仲裁电路可以选择那些和load指令不存在相关性的指令,称这两个周期为Independent Window(简称IW)。
- 而从load指令开始将相关的指令进行唤醒,直到它发现自身是否会D-Cache命中/缺失,中间也间隔了两个周期,称这两个周期为Speculative Window(简称SW),示意图如图 8.47 所示。
- IW/SW可能是互相重合的;
- SW 窗口中的指令不一定就和 load 指令存在相关性,例如那些被 load指令唤醒的指令并没有马上被仲裁电路选中,就会使SW窗口中的指令其实并没有使用load 指令的结果
- IW 窗口中的指令也并不一定就和 load指令无关,因为它可能和其他load 指令的 SW窗口是重合的;
- 由于发现 D-Cache缺失时,那些和 load 指令存在相关性的指令都需要重新被放回发射队列中并等待被唤醒,这就需要这些指令重新在发射队列中变为not ready的状态,并重新向仲裁电路发出申请,这个过程称为replay。
- replay有两种方式:issue queue based replay, replay queue based replay;
- ?issue queue based replay
- 指令被仲裁电路选中之后,不会马上离开发射队列(Issue Queue),只有当这条指令被确认已经正确执行之后,才会允许这条指令离开发射队列。
- 此种方式需要增加一个bit, issued, 指示已经被选中,但是还没有离开issue queue;
- 当这个标志位为1时,这条指令就不会再向仲裁电路发出请求信号了;
- 当这条指令需要replay时,会将issued标志位清零,这样它就可以继续向仲裁电路发出请求信号;
- 可能会发生replay的场景可能有:
- 采用交叠(interleaving)结构的D-Cache中的bank冲突
- store/load指令的违例(即按照程序中规定的顺序,load指令比拥有相同地址的 store 指令先执行了),
- 甚至是 load/load 指令的违例(即按照程序中规定的顺序,load指令比拥有相同地址的load指令先执行了,在某些多核应用环境中要求保持这种顺序)
- 等等,都需要进行replay;
- 解决方式:
- 让所有的指令在被仲裁电路选中的时候,都不要马上离开发射队列,只有当这条指令确认自己可以正确执行的时候,才会离开发射队列;
- 怎么知道一条指令的执行是正确的?
- out-of-order处理器中,load/store乱序,即使load已经命中,或者执行完了,但是只要store/load的顺序不对而导致load指令的结果是错误的,此时需要将load及其相关的指令,都进行replay;
- 这种处理器中,只有该指令retire的时候,才能保证是正确执行的,此时才能离开发射队列;
- 这种基于issue queue replay的方式,有部分指令因为d-cache hit的概率很高,发生store/load的概率也不高,所以其实大部分指令,在被仲裁电路选中之后,已经不会replay了,但是这部分指令,仍然占据着发射队列的空间;
- --> 降低了实际可以使用的容量;
- 采用折中的方式:
- 只对load指令采取issue queue based replay的方式, 一旦load指令在其执行阶段得到了D-cache hit的结果,则将发射队列中的相关指令进行释放;
- 这种方式,如果发生了store/load违例,或者load/load违例,此时可能该load指令已经离开IQ, 此时已经没有办法,因为IQ已经满了的原因,该指令无法重新放回IQ,可能会产生死锁:
- 在发射队列中的指令等待被它前面的指令唤醒,而前面的指令由于发射队列中没有空间而无法进行replay,也就无法将其他指令进行唤醒,这就产生了死锁。
- 因此,对于store/load指令违例,或者load/load指令违例的这些情况,是没有办法依靠发射队列进行replay的,这时候需要将那些需要replay的指令从流水线中抹掉,从1Cache中重新将这些指令取出来放到流水线中,当然这样会损失一些性能,这就是一种折中了;
- 对于load指令,仍然使用issue queue进行replay;
- 一种简单的方式:将所有在load指令之后,被selcet的指令,都放回发射队列;(注意,并不是真的将指令放回到发射队列中,因为这些指令还都没有离开发射队列,只需要更改对应的状态位就可以了)
- 这种方法当然不会产生错误,但是,考虑到IW窗口的存在,甚至是在一条load指令的SW窗口中,未必所有的指令都是和load指令相关的,所以这种方法将很多本来可以不需要replay的指令也进行了replay,在一定程度上损失了一些性能,但是实现起来相对是比较简单的,这种方法被称为Non-SelectiveReplay;
- 进一步改进:
- 处于IW窗口中的指令,是肯定和对应的load指令不存在相关性的。
- 在图 8.50 中,当load指令在流水线的Data阶段发现 D-Cache miss时,处于 Cal Addr 和 TLB/Tag 这两个流水段的指令,是不需要进行 replay 的,
- 因此只需要将RF和Select这两个流水段的指令从流水线中抹掉,重新在发射队列中等待被唤醒就可以了,这样可以在一定程度上减少性能的损失,可以称为是改良版的NonSelective Replay 的方法。
文章来源:https://blog.csdn.net/zhangshangjie1/article/details/135064162
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!