超线程(hyperthreading)是Intel推的一种并发线程技术,在Intel的Atom,Core i3, Core I5, 安腾等主流芯片上都已经实现。你可以把它看成一种虚拟化,即把一个物理CPU,虚拟成两个逻辑CPU,这两个逻辑CPU共用相同的运算核心,比如寄存器堆,加法器,浮点运算,向量运算部件之类的都共用。
既然要模拟两个逻辑CPU,那肯定有不公用的,就是存储状态的所有逻辑寄存器。这样,一个物理寄存器就可以通过片内保存和恢复所有寄存器的方式来实现两个虚拟CPU之间的切换。这个切换过程对软件和操作系统透明,所以在操作系统中,若有超线程,我们能看到两倍的处理器核数。
于是,问题来了,cache呢?分支预测还做吗?寄存器中的数据依赖呢?流水线上未完成的指令也保存吗?最简单的方式,全都得刷新,但明显,刷新性能会变差很多,不可行,但可以在每个cache,流水线队列,这些需要切换并存储状态的位置,先增加1倍的容积,再添加一个标志位,这样应该可以避免刷cache之类的。当然,具体细节肯定没有这么简单,欲知详情,请转到参考2。
两个逻辑CPU需要调度吗?答案是肯定的,OS只认识逻辑CPU,物理CPU还需要调度逻辑CPU。何时切换?首先CPU运算在何时会停顿?cache缺失,分支预测失败,等待前一指令执行结果等等都有可能造成CPU停顿,停顿时间从几拍到几百拍不等。切换工作都在X86指令变换位uops微指令之后,通过微指令调度器来实现,参考2中说,这时的调度已经没有逻辑上的概念了,可以把两个逻辑CPU上的线程混合起来调度。同时,对于cache来说,如果两个逻辑寄存器的微指令混合调度,就意味着cache的预测和存取可能存在冲突。还有死锁问题,等等。
最后,超线程技术到底适合什么样的程序呢?很显然,多线程程序的性能提升最大,本来操作系统要做的调度,上下文保存和恢复工作,由CPU做,而且CPU做仅仅在片内保存,大大降低开销。因为增加了并发执行能力,系统的响应时间也大大提升。
那对于每个线程内的程序呢?最小化CPU冲突很关键,如何最小化呢?尽可能把线程差异化,比如把计算和IO密集操作不要混在一个线程内,把浮点和整点运算尽量分在不同的线程中。对于访存,则看重同化,尽量让可能同时执行的线程访问相同的内存,这样共用cache,会降低物理CPU的cache缺失率。
咳咳,写了这么多,本博的一个想法是,根据上面的要求调程序真的有必要吗?如果能花钱雇得起这种程序员,一个月一两万的薪水,还真能买几个好CPU了,唉怎么跑怎么跑!价格便宜量又足。一个超线程,intel才只敢吹30%的性能提升,多买几个CPU,轻轻松松上50%。不过对于多线程,大规模并发的大型网站服务器,超线程是个绝对好选择。
参考:
- http://en./wiki/Hyper-threading
- Hyper-Threading Technology Architecture and Microarchitecture, technical description of Hyper-Threading