Simultaneous Multithreading
-
SMT的目标:在长指令延迟和每个线程可用并行度有限的情况下,显著提高处理器利用率
-
超标量处理器中不同技术对Issue slots的应用情况
- 水平浪费:在部分使用周期中浪费了发射机会
- 垂直浪费:完全浪费周期
- single-threaded superscalar:会出现较多的水平浪费和垂直浪费
- fine-grain multithreaded superscalar:每一个周期都会切换一次并且没有代价,能够利用线程间的并行性来掩盖某些长指令延迟,但是无法在一个时钟周期内使用线程间的并行性
- SMT:允许在同一个周期发射来自不同线程的指令,从而既能够掩盖长延迟,也能够增加指令并行性
-
SMT的可能的阻碍
- 线程间共享处理器资源的问题:
- 额外的资源竞争和局部性的损失
- 需要更多的caches,TLBs,分支预测逻辑,取指带宽和指令调度机制
- SMT的复杂性
- 从多个程序的不同PCs中取指,多个译码流水线
- 多个寄存器组,寄存器和功能单元之间的互连结构会更加复杂,并且寄存器的访问将会变慢
- 指令调度。如果每个线程的指令是单独分开存放的,此时调度将需要是分布式的,同时也会更加复杂
- 线程间共享处理器资源的问题:
-
SMT对某些组件可能的影响
- 寄存器端口(register ports):每一个线程都由一个单独的寄存器文件,同时寄存器文件的端口数是一个线程在一个周期可以发射的指令数目的函数
- 指令之间的相关检查:如果可以发射的指令分布在线程之间,那么需要并行检查的指令数量会随着单个线程在一个周期内发出的指令的数量增加而增加。同时并行解码的数量和取指单元的数量也会随之增加。
- 前递(旁路)逻辑:逻辑的开销主要和功能单元的数量相关,因此SMT对于前递逻辑不会有变化。
- 硬件指令调度:因为发射队列中包括不同线程的指令,因此分布式的指令调度机制将会更加复杂。在SMT中通过减少线程和功能单元之间的连接数量可以在一定程度上减少这种复杂程度
-
SMT的问题
- 共享的执行单元会带来竞争问题,例如issue slots和功能单元。这个时候低优先级的线程会比高优先级的性能下降很多
- 共享L1 cache所带来的问题。共享的线程会使得cache的局部性被降低。共享的TLB也会降低性能。
- 由于访问模式的不同,私有的I cache相对于私有的D cache效果更好
-
SMT需要在对传统OOO超标量处理器的硬件改动
- 多个PC和每个周期选择其中一个PC用于取指的逻辑(round-robin,并且保证选择的线程没有出现I-cache miss)
- 分开的返回栈,每个线程一个,用于预测子函数的返回地址
- 每个线程一个指令退出流水线逻辑,指令队列刷新逻辑(flush),陷阱处理机制
- 在BTB中,每个表项有一个线程号
- TLB的tags域包含着线程号或者进程号
- 一个更大的寄存器文件,用于所有线程的寄存器重命名。寄存器文件的大小会影响流水线和load相关指令的调度。流水级因为更大的RF,需要增加额外的两级用于读取和写回寄存器(两个周期)
- 增加fetch和exec之间的距离,从而增加了misprediction所带来的penalty,1个周期
- 额外的写回周期会增加额外的bypass逻辑
- 增加了queue到exec之间的距离,增加了在确定分支预测错误之后,发现错误路径指令的时间
- 在rename到commit之间的时间增加,会使得所有运行中的指令保存寄存器的时间变长,即会增加对寄存器池的压力
- 因为所有线程的指令之间的关系被寄存器重命名解决了,因此发射逻辑并没有变化。
-
基本的SMT硬件结构的改进
- 问题:吞吐量的峰值在8线程之前就到达了峰值,处理器的利用率小于50%。可能的原因:IQ大小,取指吞吐率,缺少并行性
- 改进取指单元,找到更加有用的指令
- 选择指令发射
-
改进SMT——取指单元的改进
-
多个线程共享一个取指单元会带来严重的资源竞争问题,从而使得取指成为SMT的瓶颈。
-
划分取指单元。单线程中的分支指令会对结果有很大的影响。因此希望从更多的线程中同时取指。例如同一个周期可以同时从两个线程中取4条指令(RR 2.4),或者是4个线程中取两条指令(RR 4.2)。
- 硬件开销:地址多选器,多个地址总线,输出的选择逻辑和cache bank的冲突检查逻辑,多个hit/miss计算逻辑。
- 硬件开销:地址多选器,多个地址总线,输出的选择逻辑和cache bank的冲突检查逻辑,多个hit/miss计算逻辑。
-
在取指单元中选择线程。在每个周期选择最佳的线程来取指。
- 评价线程的两个方面:早期分支预测错误而导致的错误路径执行的概率;取到的指令需要等待执行的时间
- 评价参数:BRCOUNT(线程在流水线中未解决的分支指令的个数);MISSCOUNT(D cache miss的数量);ICOUNT(线程在流水线中的指令数,越少优先级越高);IQPOSN(线程的指令在IQ中的位置,越靠前,优先级越低)
-
非阻塞的取指单元。由于IQ被完全使用或者是I cache miss都会使得取指阻塞。因此提供两种解决方案;
- BIGQ:IQ的大小会决定访问的时间,因此考虑在增加IQ大小的同时,控制IQ需要遍历的数量,从而保证访问时间不会增加
- ITAG:提前执行I cache的tag查找,从而减少由于指令缓存缺失带来的问题。在前端流水线之前之前增加一个流水级,提前获取fetch的地址,但是因此也会增加misfetch和misprediction的惩罚。此时需要为指令cache的tag增加额外的端口,以便于需要替换的线程也可以同步查找tag
-
-
SMT改进——改进发射逻辑
- issue slot的浪费来源:错误路径上的指令和乐观的指令发射。后者是指在未确定load指令可以命中cache之前就将相关的之后发射出去。在单线程的情况下,在发射队列中最老的指令将最有可能不发生错误,但是在SMT中,指令在队列中的位置将无法指示这种关系
- IQ发射的几种策略
- oldest_first:最老的指令优先级最高。
- opt_last:在发射所有其它指令之后,在发射和load相关的指令
- spec_last:在所有其它指令之后,再发射推测式指令。推测式指令为同一线程中的分支之后的指令
- branch_first:尽可能早的发射分支指令,以提前知道错误预测指令
- 相对于第一种方案,其它方案都需要多次搜索IQ,因此默认方案仍旧表现很好
-
尽管在多线程系统中,单线程性能会有所下降,但是大多数情况下,每个应用程序都将受益于系统吞吐量的提高,从而减少响应时间。在典型的系统中,响应时间的主要贡献者是排队时间,等待处理器中的其它作业。同步多线程通过增加处理器吞吐量和允许更多的作业同时进入处理器,能够大大减少排队时间。