本节书摘来自华章计算机《高性能科学与工程计算》一书中的第1章,第1.5节,作者:(德)Georg Hager Gerhard Wellein 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1.5 多线程处理器
所有现代的处理器都以高度流水线化来提高性能(如果可以使用流水线)。前面提到,一些因素会影响流水线的高效利用:相关性、存储延迟、不确定的循环长度、指令混合以及分支判断错误等(参考2.32节)将导致流水线频繁等待,很大一部分执行资源处于空闲状态(见图1-19)。不幸的是,这种情况是规则而不是意外。为了提高时钟频率而尽可能设计长流水线会增加算法的复杂性,结果导致没有获得成比例的性能提升,处理器也会有更多的功耗。
![b20f21e3d8a571ec1483a1a5ea4b381b50139497](https://i-blog.csdnimg.cn/blog_migrate/2cebb6b4f7f3b45db3d0fedbc36845c3.png)
正是由于这个原因,到很多现代的处理器设计中加入了线程,也叫做超线程技术(Hyper Threading)[V108,V109]或者实时多线程(Simultaneous Multithreading,SMT)。这种设计的特点是CPU核的结构状态多次复现在不同的线程中,结构状态包括数据、状态和控制寄存器,还有栈和指令指针,但诸如算术运算器、cache、内存接口等执行资源没有重复。由于多个结构状态的存在,CPU看起来像是包含了一组核(有时也叫逻辑处理器),可以并行执行多个指令流或者线程,而不用理会它们是否属于同一个程序。硬件必须记录指令属于哪个结构状态。所有线程共享这些执行资源,所以由流水线阻塞而产生的气泡可以用另外一个线程的指令来填充。如果存在并行运行的多个流水线(参见1.2.4节),一个线程搁置了或者多个流水线正处于空闲状态,则另一个线程就可以使用它们,参见图1-20。
" >
SMT可以通过多种不同的方式实现。这些方式的一个不同点是在流水线上线程如何实现切换。理想的情况切换按周期发生,但是很多实现方式需要将流水线全部清空来支持另外一个线程,这会带来非常大的延迟。
如果多个线程的代码既可以发射在同一流水线内也可以发射在不同的流水线上,则SMT可以提高指令的吞吐量。如果不同的线程使用不同的执行资源,比如浮点运算和整数运算,就很容易提高吞吐量。一般以浮点操作为主的科学计算,经过很好的优化后,并不能从SMT中获益太多,但是也有例外:在一些架构上,内存引用表的数量与现线程数量一致时,同时运行足够多的线程就能够充分利用主存带宽。
如果对于拥有SMT的线程资源有限,单个指令流的性能不会提高,甚至会有小小地下降。并且,多个线程共享很多资源尤其是cache时,如果代码对cache容量敏感就很可能增加cache容量冲突(由高速缓存容量较小引起的容量冲突)。最后,SMT会严重增加同步操作的开销:如果同一物理核执行的几个线程都通过执行紧凑的自旋等待循环等待某些事件,它们将竞争共享的执行单元,这将导致很大的同步延迟。[132,133,M41]
如果系统上有多个物理核,并且操作系统和程序员了解SMT机制,那么在不同物理核上默认运行不同程序的线程和进程是一个不错的想法,但只有在确保安全时才使用SMT来提高总体性能。SMT的出现,仿射机制将比在多核芯片上更重要(参考1.4节和附录A)。对于手头的应用程序,需要彻底测试才能确定SMT机制是否能提高性能。如果不能在一个物理核上通过合适仿射应该只保留一个逻辑核,并且如果可能的话SMT应该被一起关掉。