Microarchitecture: HyperThreading(超线程)

线程并行

当代的软件趋向于运行在多线程模式,或者是并行处理。网络包传输和web服务可以运行以多线程的方式运行以达到更高的性能。甚至是桌面应用也开始增加并行性。Intel架构师已经开始尝试利用TLP( thread-level parallelism) 线程并行性,用来在较少的晶体管和功耗下就能达到更高的性能。

高端和终端的服务器市场,多核已经被广泛的使用,已获得更高的性能。通过增加处理器,应用可以通过在更多的处理器上运行更多的线程已达到更高的性能。这些线程可能属于同一个应用,也可以属于不同的应用。多核系统已经被使用多年,高端程序员已经可以熟练的利用多核来达到更高的性能。

近几年,大家讨论了一些提高TLP的技术,也提出了产品。比如CMP(chip multiprocessing),两个处理器被放到了一个die上。这两个处理器都各自拥有完全的组件和架构资源。处理器之间可以共享更大的片上cache。 CMP和传统的多核系统基本无关,你可以在传统的多核系统上使用CMP芯片。然而,CMP chip 将会比单核chip面积上大的多,因此造价更高。并且这也没有解决die的面积和功耗问题。

另一种方法就是通过线程切换,允许单核去执行多线程。通过时间片切换,实现多线程切换。然而这将导致多余的执行,但是可以有效地减少访问memory导致的latency。如果多线程基于event切换,那么当多线程遇到cache miss的情况时,可以有效地减少latency。这个方法对于大量cache miss 和执行类似任务的线程很有效。但是时间片或者是基于event切换都没有实现提高资源的利用效率,比如分支预测失败和指令依赖。

最终,可以用过单核,不切换的方式实现多线程。线程可以同时执行,以更高效的利用资源。这个方法可以最大资源的利用效率。在单位晶体管和功耗时,实现了性能的最大化。

Hyper-Threading 技术为intel 架构提出了多线程的方法。这篇文章我们将要讨论在Xeon 处理器家族中,Hyper-Threading技术的首次应用。

Hyper-Threading技术架构

Hyper-Threading 在单个物理处理器上实现了多个逻辑处理器。我们为每一个逻辑处理器都做了一份architecture 状态的拷贝,逻辑处理器之间共享物理执行资源。从软件到架构的角度,这意味着操作系统或者是用户的程序可以像在多核处理器上调度多线程一样,在单核上调度多线程。从微架构的角度,这意味着逻辑处理器将会在共享的执行资源上执行不同线程的指令。

图2展示了多核系统上,两个没有采用hyper-threading技术的物理核心。图3展示了采用了hyper-threading技术的多核系统。通过在每个物理核心上实现两份逻辑核心状态的备份,系统就看起来有四个逻辑核心。

Hyper-Threading 技术首次实现在Xeon家族的双处理器和多处理器服务器上。通过有效地利用更多的处理器资源,Xeon 处理器产品可以有效地提高性能。Hyper-Threading技术增加了小于5%的芯片面积和功耗,但是提供了更多的性能。

 

 

每一个逻辑处理器都维持一份完整的架构状态。架构状态包括寄存器(通用寄存器,控制寄存器和中断控制寄存器以及状态寄存器)。从软件的角度看,一旦架构状态有多份,那么处理器可以虚拟的看成两个处理器。存储架构状态的寄存器的晶体管的数量是非常小的。逻辑处理器之间基本上共享了所有的资源,比如cache,执行单元,分支预测,控制逻辑以及总线。

每个逻辑处理器都拥有自己的中断控制器,因此中断可以发送给指定的逻辑处理器,并且准确的被相应的处理器处理。

Hyper-threading 技术在Intel Xeon 产品中的首次应用

在Xeon产品中实现Hyper-Threading技术时,预先设定了几个目标。其中一个是在实现Hyper-Threading的同时最小化die的面积。因为逻辑处理器共享了主要的微架构资源,仅仅有少部分结构被复制,因此实现该技术的面积占用了全die面积不到5%。

第二个目标是当一个逻辑处理器阻塞时,另一个逻辑处理器可以继续工作。一个逻辑处理器可能会因为cache miss,处理branch预测失败和等待依赖的指令执行完毕而暂时的阻塞一段时间。独立的前向工作流应当保证在两个线程同时执行时,没有逻辑处理器可以占用全部的资源。这是通过划分或者限制每个thread可以拥有的资源数量实现的。

第三个目标是单线程软件在hyper-threading处理器上运行时应当拥有和普通处理器一样的速度。这意味着,如果单线程运行在处理器上,那么它将拥有全部的资源。从更高的角度看,微架构的pipeline如figute4所示,其中缓冲队列将pipeline分割。Queue要么被对半分,要么被复制,以保证每个线程都可以独立的前行。

 

接下来的章节我们将会梳理pipeline,讨论一下主要的功能,并且阐述资源的共享与复制。

Frond End 前端

流水线的前端负责将指令传输给后续的pipe 阶段。如图5-a所示,指令最初从Execution Trace Cache(TC)或者L1 指令cache中获得。图5-b表明只有TC miss的时候,cpu才从L2 Cache中取指,译码。靠近TC的是微指令ROM(Microcode ROM),存储为较长,较复杂的IA-32指令存储译码过的微码。

 

Execution Trace Cache (TC)

TC存储译码过的指令,也称作微指令。大多数程序中的指令都是从TC中取出并执行的。独立的两组指令PC用于追踪各自的线程的执行。两个逻辑处理器可以每周期仲裁一次,以获得TC的所有权。如果两个逻辑处理器在同一时刻拥有权限,那么将会仲裁给一个,在下个周期仲裁给另一个。比如,如果两个逻辑处理器都请求trace cache的权限,第一个周期为一个逻辑处理器取指令,那么下一个周期则为另一个处理器作用。如果一个逻辑处理器阻塞了,不能够使用TC,那么另一个逻辑处理器将可以每个周期都全带宽的访问TC。

TC Entry被线程信息所标记,并且可以按照需要动态的分配。TC结构为8路组相连,使用LRU替换算法。共享的特性可以使一个逻辑处理器在需要的情况下,拥有比另一个更多的Entry。

Microcode ROM

当遇到了复杂的指令时,TC发送一个微指令指针给Microcode ROM。Microcode ROM将会控制取微码,然后将控制权返回给YC。两个逻辑处理器拥有各自独立的微指令指针。

逻辑处理器也共享Microcode ROM。访问Microcode ROM的权限在两个逻辑处理器之间切换。

ITLB 和 分支预测

如果TC miss,将会从L2 Cache中取指,解码为微码后,存入TC中。ITLB接收到来自TC对指令的请求,ITLB将下一条指令的地址(PC)翻译为物理地址。请求被发送给L2 Cache,并得到来自L2 Cache的响应。这些指令将会存放在streaming buffer,直到他们被译码。

在hyper-threading中,ITLB被复制了两份。每个逻辑处理器有它自己的的ITLB,而且都有自己得一套指令指针,以追踪程序的PC。取指逻辑负责向L2 Cache发送请求,它会基于先来先处理的准则,对取值逻辑进行仲裁。一般会为两个逻辑处理器至少处理一个请求。因此,两个逻辑处理器可以同时有pending的取指。

每个逻辑处理器都有一套64-byte的stream buffer,为指令解码阶段缓存指令。ITLB和streaming buffer都是较小的结构,因此这个结构的复制对die的面积占用较小。

分支预测结构可以是复制的或者共享的。用于预测返回指令地址的Return stack buffer也被复制了,因为这是一个非常小的部件,并且call/return pair的预测根据独立的线程进行预测会更加准确。BHB(分支历史缓存)用于在global history array中为每个逻辑处理器查找全局历史。然而,因为global history array很大,因此这是一个共享结构,其内部项会被逻辑处理器ID号打上tag。

IA-32 指令译码

IA-32 指令是译码起来是非常笨重的,因为指令是变长的,并且有不同的选择。译码将会花费大量的逻辑和临时状态。幸运的是,TC 会命中大部分的uop,因此我们只需要在TC miss的时候译码。

译码逻辑从stream buffer中取出指令,将其译码为uop。当两个线程同时译码时,stream buffer会在线程之间切换,因此线程会共享译码逻辑。译码逻辑需要为两个线程保存中间状态,即使它只为一个逻辑寄存器译码。总体上说,在切换到另一个逻辑处理器之前,会有另一个逻辑处理器的几条指令被译码。我们会基于die的大小以及复杂性来确定逻辑处理器切换的颗粒度。当然,如果只有一个逻辑处理器需要译码,那么它会占据全部的译码带宽。译码指令将会被写入TC,并forward到uop队列中。

Uop队列

Uop来自以下三个来源:

  1. Trace cache
  2. Microcode ROM
  3. 译码逻辑

Uop会被放置到uop queue中。这个queue将front-end即前端和乱序执行执行单元解耦。Uop queue根据逻辑处理器分为两半。切换使得逻辑处理器可以有独立的forward逻辑,不会因为另一个逻辑处理器的TC miss或者是执行单元的暂停而阻塞。

乱序执行单元

乱序执行单元由分配、寄存器重命名、调度和执行单元组成,如图6所示。这部分乱序的执行指令。一旦他们的输入准备好,就立刻执行,而不考虑原本的程序中的指令顺序。

 

分配

乱序执行单元有缓冲buffer用于执行重排序,跟踪和顺序操作。分配器从uop queue中取出uop,然后分配执行uop所需要的buffer。缓冲buffer包括 126项重排序buffer, 128个整数和128个浮点物理寄存器,48个load 和 24个store 项buffer。我们拆分了其中的几个重要buffer,所以每个逻辑处理器可以最多使用其中的一半数目。比如,逻辑处理器最多可以使用63个re-order buffer,24个load buffer和12个store buffer。

如果两个逻辑处理器在uop queue都有uop要处理,分配器将会每个周期都为逻辑处理器切换。如果逻辑处理器已经使用了它所分配的资源的上限,那么分配器将会向这个逻辑处理器发送一个暂停信号,而后为另一个逻辑处理器分配资源。如果uop queue中只包含一个逻辑处理器的uops,那么分配器将会每个周期都为这个逻辑处理器继续分配资源,以优化分配带宽,尽管还需要满足资源上限条件。

通过限制关键buffer的资源占用限制,可以公平的对待每个逻辑处理器并且避免死锁。

寄存器重命名

寄存器重命名将IA-32寄存器命名为物理寄存器。这将会使8个通用IA-32整数寄存器变为动态可调节的128个物理寄存器。重命名逻辑通过寄存器重命名表格(RAT)以追踪最新的架构寄存器。这样新来的指令就可以明确其操作数架构寄存器对应的物理寄存器。

因为逻辑处理器需要维护并追踪自己的完整的架构状态,因此我们为每一个逻辑处理器都设置了一个RAT。重命名过程与上述的分配逻辑并行执行。因此分配器和寄存器重命名会同时处理相同的uops。

一旦uops已经完成了分配和寄存器重命名,他们就会被分配到两组queue中,一组作用域寄存器操作(load and store),另一组负责所有的其他操作。这两组queue分别叫做存储指令队列和通用指令队列。这两组队列也被切分,每个逻辑寄存器最多使用一半。

指令调度

指令调度是乱序执行的关键所在。五个uop调度器用于在不同的执行单元之间调度不同类型的指令。每周期可以最多派发6条uops。如果uops的输入操作数准备好了,并且执行单元已经空出,可以使用,那么调度器将会选择哪个uops可以开始执行。

存储指令队列和通用指令队列会尽快的将uops发送到五个调度队列。如果需要的话,会每周期为逻辑处理器切换操作。

每个调度器都有自己的8项到12项的调度队列。调度器从调度队列中选择uops,发送给执行单元。调度器不会基于uops究竟属于哪一个逻辑处理器来选择uops。也就是说,调度器无视逻辑处理器。Uops可以仅仅根据输入操作数和执行单元而被选择。举个例子,调度器可以同时分配两个逻辑处理器额各自两条uops。为了避免死锁,并且保证公平,我们队逻辑处理器在调度队列中的数目上限进行了设置。这个上限值取决于调度队列的大小。

执行单元

执行单元和存储层次也不会区分不同的逻辑处理器。因为源寄存器和目标寄存器已经在同一个物理寄存器池中被重命名,因此uops仅通过读取物理寄存器文件可以知道其目标寄存器对应的物理寄存器。通过比较物理寄存器的编号就可以将操作结果forward给其他的uops,而不需要明确逻辑寄存器号。在执行之后,uops被存放到重排序缓冲中。重排序缓冲将执行阶段和retire阶段解耦。重排序缓冲为每个逻辑处理器各分一半。

退休单元

Uop退休逻辑将会按照程序的顺序改变架构状态。退休逻辑会追踪两个逻辑处理器中的待退休指令。然后通过在两个逻辑处理器之间切换,并按照程序的顺序提交、改变架构状态。退休逻辑会为一个逻辑处理器退休uop,然后切换到另一个。如果一个逻辑处理器一直没有准备好退休uop,那么退休单元会全力退休另一个逻辑处理器。

一旦store退休,store的数据需要被写入第一级data cache。选择逻辑会在逻辑处理器之间切换,以将数据存储到cache中。

Memory 子系统

Memory子系统包括DTLB,L1 data cache , L2 data cache 和L3 data Cache(L3 cache只在Xeon处理器中有)。对memory子系统的访问也不考虑逻辑处理。存储子系统只是来了请求,就处理。

DTLB

DTLB将逻辑地址翻译为物理地址。它是64路全相连。每一项可以映射4K或者4M page大小。尽管DTLB是两个逻辑处理器中共享的结构,但是每一项都会包含一个处理器ID。每个逻辑处理器都有自己的一个保留寄存器以保证公平性和在DTLB miss时,进行forward。

L1 Data Cache, L2 Cache,L3 Cache

L1 data cache是4路组相连,每个cacheline 64 byte。它是写直达cache,这意味着写操作也会直接写入L2 Cache。L1 Cache 是虚拟地址索引,物理地址做tag。

L2 和 L3 Cache是8路组相连,每个cacheline 128 byte。L2 和L3 cache是物理地址索引。逻辑处理器之间共享cache。

因为逻辑处理器共享cache,因此可能有潜在的cache冲突,这可能会导致更低的性能。但是也可能会存在共享cache中的数据。比如,一个逻辑处理器可能预取另一个处理器需要的指令或者数据。这在服务器应用程序中很常见。在生产者-消费者模型中,一个逻辑处理器可能产生另一个逻辑处理器需要使用的数据。在这类case中,可以挖掘潜在的更高的性能。

BUS

如果cache miss,那么逻辑处理器将会访问bus logic。Bus logic包括本地的APIC中断控制器,也包括片外的系统存储和I/O 空间。总线逻辑也处理来自外部总线对cacheable 地址的snoop请求和本地APIC输入的终端。

从服务的角度来看,逻辑处理器的请求是根据先来先处理的原则。Queue和Buffer空间是共享的。我们不会给其中的一个逻辑处理器优先权限。

我们也会区分来自不同逻辑处理器的请求。对本地APIC的请求和中断资源是唯一的,并区分不同的逻辑处理器。总线逻辑也会基于逻辑处理器来处理barrier fence(屏障操作)和memory order操作。

对于debug功能,逻辑处理器的ID号被显示的发送给处理器的外部总线。其他的总线操作,如cache line evict和预取操作,会根据产生transaction的请求来获取逻辑处理器的ID号。

单任务和多任务模式

当一个软件线程要执行时,为了优化性能,提供了两种模型多任务模型(multi-task MT)和单任务模型(ST)。在MT模式中,有两个工作的逻辑处理器,其中的一些资源被如前所述的方式切分。ST模式分为两种,single-task 逻辑处理器0(ST0)和single-task 逻辑处理器1(ST1)。在ST-0或者ST-1模式中,只有一个逻辑处理器处于工作状态。在MT模式中被切分的资源被单个处理器畅享。IA-32 Intel 架构有一个指令叫做HALT,将会停止处理器的执行,然后使得处理器进入低功耗状态。HALT是一条特权指令,这意味着只有操作系统或者其他的ring-0级别的程序可以执行这条指令。用户级别的程序是不可以执行HALT执行的。

如果处理器采用了Hyper-Threading技术,执行HALT指令,处理器将会从MT模式切换到ST-0或者ST-1模式。比如,如果逻辑处理器0执行HALT,那么只有逻辑处理器1处于工作状态。那么物理寄存器将会处于ST-1模式。先前被切分的资源将会被逻辑处理器1全部助战。如果逻辑处理器1也执行了HALT操作,那么物理处理器可以进入低功耗状态。

在ST0或者ST1模式中,中断发送给已经HALT的处理器将会导致处理器进入MT模式,操作系统负责管理MT模式的切换。

图7总结了上述的讨论。在ST0或者ST1模式资源被完全分配给单个逻辑处理器。在MT模式,资源在两个逻辑处理器间共享。

操作系统和应用程序

使用了Hyper-Threading 技术的处理器在操作系统和应用程序看来,处理器核心数翻倍。操作系统将会当把逻辑处理器当做物理处理器进行管理,调度程序和线程。然而,为了达到最高的性能,操作系统会实现两种优化。

第一种是如果仅有一个逻辑处理器active使用HALT指令。使用HALT将会使处理器进入ST0或者ST1模式。不使用这个优化的操作系统将会在一个逻辑处理器idle,另一个逻辑处理器active的处理器上工作。并且idle的逻辑处理器会持续的判断是否有人物要执行,这个叫做idle loop。Idle loop将消耗执行资源,如果这些执行资源释放,那么性能将会更高。

另一种优化就是将软件线程调度到逻辑处理器上。总体上来说,为了更好的性能,操作系统将会在调度线程到相同的物理处理器之前,调度线程到不同的物理处理器上。这个优化将会使得线程尽可能的执行在不同的物理核心上。

性能提升

在单核处理器和多核处理器上,Hyper-threading技术可以提升21%的性能。

 

在网站服务器的workload中,可以获得16%到28%的性能提升。

 

笔记:

Sub System

IP Block

Share

Duplicate

Partion

前端

Trace Cache

 

 

Microcode ROM

 

 

ITLB

 

 

分支预测

 

 

Return stack

 

 

译码

 

 

Uop 队列

 

 

乱序执行

分配

 

 

寄存器重命名

 

 

指令调度

 

 

执行单元

 

 

重排序缓冲区

 

 

存储系统

DTLB

 

 

Cache

 

 

欢迎关注我的公众号《处理器与AI芯片》
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值