Computer Architectrure: Quantitative Approch 第三章第五、六节

Dynamic Scheduling: Examples and the Algorithm

在详细研究Tomasulo的算法之前,让我们考虑一些示例,这些示例将有助于说明该算法的工作原理。

在这里插入图片描述
在这里插入图片描述

与早期较简单的方案相比,Tomasulo的方案具有两个主要优点:(1)阻塞检测逻辑的分布;(2)消除了WAW和WAR阻塞的停顿。第一个优点来自分布式预留站和CDB的使用。 如果多个指令正在等待一个结果,并且每个指令已经具有其他操作数,则可以通过在CDB上广播结果来同时释放指令。 如果使用集中式寄存器文件,则在有可用寄存器总线时,设备将不得不从寄存器中读取其结果。

第二个优点是消除了WAW和WAR危害,这是通过使用保留站重命名寄存器以及在操作数可用时将其存储到保留站中的过程来实现的。

例如,即使存在涉及f6的WAR危险,图3.11中的代码序列也会同时发出fdiv.d和fadd.d。 可以通过以下两种方法之一消除危害。首先,如果指令fdiv.d已完成,然后Vk将存储结果,从而使fdiv.d能够独立于fadd.d执行(显示的情况)。 另一方面,如果fld尚未完成,则Qk将指向Load1保留站,并且fdiv.d指令将独立于fadd.d。 因此,无论哪种情况,都可以发出fadd.d并开始执行。 fdiv.d结果的任何使用都将指向保留站,从而允许fadd.d完成并将其值存储在寄存器中而不会影响fdiv.d。

在这里插入图片描述
我们很快就会看到消除WAW危害的示例。 但是,让我们首先来看一下我们先前的示例如何继续执行。 在本示例以及本章随后的示例中,假定以下延迟:加载为1个时钟周期,加法为2个时钟周期,乘法为6个时钟周期,而除法为12个时钟周期。

Tomasulo’s Algorithm: The Details

在这里插入图片描述

Figure 3.13指定了每条指令必须经过的检查和步骤。 如前所述,加载和存储在进入独立的加载或存储缓冲区之前都要经过一个功能单元,以进行有效的地址计算。 加载需要执行第二个步骤来访问内存,然后转到写入结果以将值从内存发送到寄存器文件和/或任何等待的保留站。 存储在写入结果阶段完成其执行,该阶段将结果写入内存。 请注意,无论目的地是寄存器还是存储器,所有写操作都在写结果中发生。 该限制简化了Tomasulo的算法,通过3.6节中的推测对其扩展至关重要。

Tomasulo’s Algorithm: A Loop-Based Example

要了解通过动态重命名寄存器消除WAW和WAR危险的全部功能,我们必须查看一个循环。 考虑以下简单序列,将数组的元素乘以f2中的标量:
在这里插入图片描述
如果我们预测将采取分支,则使用保留站将允许一次执行多个此循环。 在不更改代码的情况下获得了这一优势——实际上,硬件使用重命名获得的保留站作为附加寄存器来动态展开循环。
在这里插入图片描述
假设我们已经在循环的两个连续迭代中发出了所有指令,但是没有浮点加载/存储或操作完成。 Figure 3.14显示了保留站,寄存器状态表以及此时的加载和存储缓冲区。 (忽略整数ALU操作,并假设已按预期预测分支。)一旦系统达到此状态,就可以在CPI接近1.0的情况下维持循环的两个副本,前提是乘法可以在四个时钟中完成。 周期。 由于有六个周期的等待时间,在达到稳定状态之前,将需要处理其他迭代。 这需要更多的保留站来保存正在执行的指令。 正如我们将在本章后面看到的那样,当Tomasulo的方法扩展为多个发布指令时,每个时钟可以支持多条指令。

如果他们访问不同的地址,则可以安全地完成ld和st。如果ld和st访问相同的地址,则发生两件事之一:

  • ld是按照程序顺序存放在st之前的,互换它们会导致WAR危险。
  • st要先按计划顺序装载,互换它们会导致RAW危险。
    同样,将两个存储互换到相同的地址会导致WAW危害。

因此,为了确定是否可以在给定的时间执行加载,处理器可以检查以程序顺序在加载之前的任何未完成st是否共享与ld相同的数据存储地址。 同样,st必须等待,直到没有未执行的ld或程序顺序更早且共享相同数据存储器地址的st为止。 我们在第3.9节中考虑一种消除这种限制的方法。

为了检测到此类危险,处理器必须已计算出与任何较早的内存操作相关的数据内存地址。 确保处理器具有所有此类地址的一种简单但非必要的最佳方法是按程序顺序执行有效的地址计算。 (实际上,我们只需要保持st和其他内存引用之间的相对顺序即可;也就是说,可以自由地对ld进行重新排序。)

让我们首先考虑ld的情况。 如果我们按程序顺序执行有效地址计算,那么当ld完成有效地址计算后,我们可以通过检查所有活动st缓冲区的A字段来检查是否存在地址冲突。 如果ld地址与st缓冲区中任何活动条目的地址匹配,则在冲突st完成之前,该ld指令不会发送到ld缓冲区。 (某些实现将值直接绕过暂挂st中的ld,从而减少了这种RAW危害的延迟。)

st操作类似,不同之处在于处理器必须检查ld缓冲区和st缓冲区中是否存在冲突,因为不能相对于ld或st对发生冲突的st进行重新排序。

动态调度的管道可以产生非常高的性能,准确预测了提供的分支,这是我们在上一节中解决的问题。 这种方法的主要缺点是Tomasulo方案的复杂性,这需要大量的硬件。 特别是,每个预留站必须包含一个关联缓冲区(必须高速运行)以及复杂的控制逻辑。 性能也可能受单个CDB的限制。 尽管可以添加其他CDB,但每个CDB必须与每个保留站进行交互,并且必须在每个站为每个CDB复制关联​​的标签匹配硬件。 在1990年代,只有高端处理器才能利用动态调度(及其对推测的扩展)。 但是,最近甚至为PMD设计的处理器都在使用这些技术,而高端台式机和小型服务器的处理器也有数百个缓冲区来支持动态调度。

在Tomasulo的方案中,结合了两种不同的技术:将体系结构寄存器重命名为更大的一组寄存器,以及从寄存器文件中缓冲源操作数。 源操作数缓冲解决了当操作数在寄存器中可用时出现的WAR危险。 正如我们将在后面看到的,还可以通过重命名寄存器以及缓冲结果来消除WAR危害,直到没有剩余的对早期版本的寄存器引用为止。 当我们讨论硬件推测时,将使用这种方法。

Tomasulo的方案在360/91之后很多年未使用,但由于种种原因,从1990年代开始在多issue处理器中被广泛采用:

  • 尽管Tomasulo的算法是在缓存之前设计的,但缓存的存在以及固有的不可预测的延迟已成为动态调度的主要动机之一。 无序执行允许处理器在等待高速缓存未命中完成的同时继续执行指令,从而隐藏了全部或部分高速缓存未命中的代价。
  • 随着处理器在issue能力方面变得更加激进,设计人员开始关注难于调度的代码(例如大多数非数字代码)的性能,诸如寄存器重命名,动态调度和推测之类的技术变得越来越重要。
  • 它可以实现高性能,而无需编译器将代码定向到特定的流水线结构,这是在紧缩型大众市场软件时代的宝贵属性

Hardware-Based Speculation

随着我们尝试利用更多的指令级并行性,维持控制依赖关系成为越来越重的问题。 分支预测减少了分支的直接停顿,但对于每个时钟执行多个指令的处理器,仅准确地预测分支可能不足以生成所需数量的指令级并行度。 issue量较大的处理器可能需要在每个时钟周期执行一个分支,以保持最佳性能。 因此,利用更多的并行性要求我们克服控制依赖的局限性。

通过推测分支的结果并像我们的猜测一样执行程序来克服控制依赖。 这种机制代表了具有动态调度的分支预测的微妙但重要的扩展。 特别是,通过推测,我们获取,发出和执行指令,就好像我们的分支预测始终正确; 动态调度仅获取并发布此类指令。 当然,我们需要机制来应对推测不正确的情况。 附录H讨论了各种支持编译器推测的机制。在本节中,我们将探讨硬件推测,它扩展了动态调度的思想。

基于硬件的推测结合了三个关键思想:(1)动态分支预测以选择要执行的指令,(2)推测允许在解决控制相关性之前执行指令(具有消除错误推测的序列影响的能力),(3)动态调度以处理基本块的不同组合的调度。 (相比之下,不进行推测的动态调度只会部分重叠基本块,因为它要求在实际执行后续基本块中的任何指令之前先解析一个分支。)

基于硬件的推测遵循预测的数据值流,以选择何时执行指令。 这种执行程序的方法本质上是一种数据流执行:只要操作数可用,就立即执行操作。

为了扩展Tomasulo的算法以支持推测,我们必须从指令的实际完成中分离出在指令之间进行结果的绕行,而推测是执行推测性执行一条指令所必需的。 通过进行这种分离,我们可以允许一条指令执行并将其结果绕过其他指令,而不允许该指令执行任何无法撤消的更新,直到我们知道该指令不再是推测性的。

使用旁路值就像执行推测寄存器读取一样,因为直到该指令不再是推测性的,我们才知道提供源寄存器值的指令是否提供了正确的结果。 当指令不再是推测性的时,我们允许它更新寄存器文件或存储器; 我们在指令执行序列指令控制中将此步骤称为附加步骤。

实施推测背后的关键思想是允许指令乱序执行,但迫使它们按顺序执行,并防止任何不可撤销的动作(例如更新状态或采取例外措施)直到指令提交为止。 因此,当我们增加推测时,我们需要将完成执行的过程与指令提交分开,因为指令可能在准备提交之前就已经相当大地完成了执行。 将此提交阶段添加到指令执行序列中需要另外一组硬件缓冲区,这些缓冲区用于保存已完成执行但尚未提交的指令结果。 该硬件缓冲区(我们称为重排序缓冲区)也用于在可能被推测的指令之间传递结果。

重新排序缓冲区(ROB)以与Tomasulo算法中的预留站扩展寄存器集相同的方式提供其他寄存器。 在与指令相关联的操作完成与指令提交之间的时间之间,ROB保留指令的结果。 因此,ROB是指令操作数的来源,就像预留站以Tomasulo的算法提供操作数一样。 关键的区别在于,在Tomasulo的算法中,一旦一条指令写入了结果,所有随后发出的指令都将在寄存器文件中找到结果。 通过推测,在指令提交之前寄存器文件不会更新(并且我们明确知道该指令应该执行)。 因此,ROB在指令执行完成和指令提交之间的间隔中提供操作数。 ROB与Tomasulo算法中的存储缓冲区相似,并且为简单起见,我们将存储缓冲区的功能集成到ROB中。

在这里插入图片描述

Figure 3.15显示了包括ROB的处理器的硬件结构。 ROB中的每个条目都包含四个字段:指令类型,目标字段,值字段和就绪字段。 指令类型字段指示指令是分支(没有目标结果),存储(具有存储器地址目标)还是寄存器操作(具有寄存器目标的ALU操作或装入)。 目的字段提供应将指令结果写入其中的寄存器号(用于装载和ALU操作)或存储器地址(用于存储)。 值字段用于保存指令结果的值,直到指令提交为止。 不久我们将看到一个ROB条目示例。最后,“就绪”字段指示指令已完成执行,并且值已准备就绪。

ROB包含存储缓冲区。 存储仍然分两步执行,但第二步由指令落实执行。 尽管保留站的重命名功能已由ROB取代,但我们仍然需要一个地方来缓冲操作(和操作数),它们在发出时间和开始执行之间。保留站仍提供此功能。 由于每条指令在提交前都会在ROB中有一个位置,因此我们使用ROB条目号而不是保留站号来标记结果。 该标记要求必须在保留站中跟踪为指令分配的ROB。 在本节的稍后部分,我们将探讨另一种实现方式,该实现方式使用额外的寄存器进行重命名,并使用一个替换ROB的队列来决定何时可以提交指令。

这是指令执行涉及的四个步骤:

1.发布-从指令队列中获取指令。 如果ROB中有一个空的预留站和一个空的插槽,则发出指令; 如果操作数在寄存器或ROB中可用,则将它们发送到保留站。 更新控制条目以指示缓冲区正在使用中。 分配给结果的ROB条目的编号也发送到预留站,这样,当将该结果放置在CDB上时,该编号可用于标记结果。 如果所有保留都已满或ROB已满,则指令发布将暂停,直到两个都有可用条目为止。

2.执行-如果一个或多个操作数尚不可用,请在等待计算寄存器的同时监视CDB。 此步骤检查RAW危险。 当两个操作数在预留站上都可用时,请执行该操作。 在此阶段,指令可能需要多个时钟周期,而在此阶段,ld仍然需要两个步骤。 st在此步骤仅需要基址寄存器,因为此时执行st仅是有效的地址计算。

3.写入结果-如果结果可用,则将其写入CDB(发出指令时发送ROB标签),然后将其从CDB写入ROB,以及等待该结果的所有保留站。 将预订站标记为可用。 商店指示需要采取特殊的措施。 如果要存储的值可用,则将其写入商店的ROB条目的“值”字段中。 如果要存储的值尚不可用,则必须监视CDB,直到广播该值为止,这时将更新商店的ROB条目的“值”字段。 为简单起见,我们假设这是在st的“Write Result”阶段发生的; 我们稍后将讨论放宽此要求。

4.提交-这是完成指令的最后阶段,之后仅保留其结果。 (一些处理器将此提交阶段称为“完成”或“毕业”。)提交时有三种不同的操作序列,具体取决于提交指令是具有不正确的预测分支、存储还是任何其他指令 (正常提交)。 当指令到达ROB的开头并且其结果存在于缓冲区中时,将发生正常的提交情况。 此时,处理器将使用结果更新寄存器,并从ROB中删除指令。 提交存储的过程与之类似,只是存储器是更新的而不是结果寄存器。 预测到达ROB的开头时,如果分支不正确,则表明推测是错误的。 刷新ROB,并在分支的正确后继者处重新开始执行。 如果正确预测了分支,则分支结束。指令提交后,将收回其在ROB中的条目,并更新寄存器或存储器目标,从而减少ROB条目。 如果ROB已满,我们只需停止发布指令,直到可以输入。 现在,让我们研究一下该方案如何处理Tomasulo算法所使用的示例。

在这里插入图片描述
在这里插入图片描述
前面的示例说明了具有推测性的处理器和具有动态调度的处理器之间的关键重要区别。 将Figure 3.16的内容与Figure 3.12的内容进行比较,该图显示了在使用Tomasulo算法的处理器上操作相同代码序列的过程。 关键区别在于,在前面的示例中,不允许在最早的未完成指令(前面的示例中的fmul.d)之后执行任何指令。 相反,在图3.12中,fsub.d和fadd.d指令也已完成。

这种差异的一个含义是带有ROB的处理器可以动态执行代码,同时保持精确的中断模型。 例如,如果fmul.d指令引起了中断,我们可以简单地等到它到达ROB的开头并执行中断,然后从ROB中清除所有其他挂起的指令。 因为指令提交按顺序发生,所以这产生一个精确的异常。

相比之下,在使用Tomasulo算法的示例中,fsub.d和fadd.d指令都可以在fmul.d提出例外之前完成。 结果是寄存器f8和f6(fsub.d和fadd.d指令的目标)可能会被覆盖,在这种情况下,中断将不精确。

一些用户和架构师在设计高性能处理器时可以接受不精确的浮点运算,因为这些计算可能会让程序终止。 有关此主题的进一步讨论,请参见附录J。而其他类型的异常(例如页面错误),则很难容纳不精确的问题,因为程序必须在处理此类异常后顺次恢复执行。

如下面的示例所示,除了支持推测执行之外,将ROB与按顺序指令提交配合使用还提供了精确的异常。

在这里插入图片描述
在这里插入图片描述

因为在执行指令之前,寄存器值和任何存储器值都不会被实际写入,所以当发现分支预测错误时,处理器可以轻松地撤销其推测性动作。 假设在Figure 3.17中第一次没有使用分支bne。 分支之前的指令仅在每个到达ROB的开头时才提交; 当分支到达该缓冲区的开头时,只需清除缓冲区,处理器便开始从另一条路径中提取指令。

实际上,推测错误的处理器会在错误预测分支后尽早恢复。 可以通过清除错误分支后出现的所有条目的ROB,允许ROB中分支之前的条目继续并在正确的分支后继者处重新开始提取来完成此恢复。 在推测处理器中,性能对分支预测更为敏感,因为错误预测的影响会更高。 因此,处理分支的所有方面(预测准确性,错误预测检测的等待时间和错误预测恢复时间)都变得越来越重要。

通过在准备好提交之前不识别异常来处理异常。 如果推测的指令引发异常,则该异常将记录在ROB中。 如果出现分支预测错误,并且不应执行该指令,则清除ROB时会与该指令一起清除异常。 如果指令到达了ROB的开头,那么我们知道它不再是推测性的,应该采取例外处理。 我们也可以尝试在异常出现且所有较早分支都得到解决后立即处理异常,但是对于异常而言,这比分支错误预测更具挑战性,并且因为它发生的频率较低,因此不那么关键。

在这里插入图片描述
Figure 3.18显示了一条指令的执行步骤,以及执行该步骤所必须满足的条件和所采取的措施。 我们展示了直到提交才解决错误预测的分支的情况。 尽管推测似乎是对动态调度的简单补充,但将Figure3.18与Figure3.13中Tomasulo算法进行比较,可以看出,推测给控件带来了显着的复杂性。 此外,请记住,分支错误预测要稍微复杂一些。

在推测处理器中处理st的方式与Tomasulo的算法之间存在重要的区别。 在Tomasulo的算法中,存储可以在达到Write Result(确保已计算出有效地址)时更新内存,并且可以存储数据值。 在推测处理器中,存储仅在到达ROB头部时才更新内存。 这种差异确保在指令不再具有推测性之前,不会更新内存。

Figure 3.18对存储进行了一项重大简化,实际上是不需要的。 Figure3.18要求st在Write Result阶段等待要存储其值的寄存器源操作数; 然后将值从st的预留站的Vk字段移到st的ROB条目的“值”字段。 但是,实际上,要st的值直到存储区提交之前才需要到达,并且可以通过ld指令直接放入存储区的ROB条目中。 这是通过硬件跟踪何时要st的源值在商店的ROB条目中可用,并在每次指令完成时搜索ROB来查找相关的商店来实现的。

这种添加并不复杂,但是添加有两个效果:我们需要向ROB添加一个字段,而Figure3.18(已经是小字体)会更长! 尽管Figure3.18进行了简化,但在我们的示例中,我们将允许st通过Write Result阶段,并只需等待该值在提交时准备就绪即可。

像Tomasulo的算法一样,我们必须避免内存中的冒险。 通过推测消除了内存操作中的WAW和WAR冒险,因为当存储位于ROB的开头时,内存的实际更新是按顺序进行的,因此没有较早的ld或st仍可以挂起。 内存的RAW冒险可以通过两个限制来避免:

1.如果st占用的任何活动ROB条目的“目标”字段与ld的A字段的值匹配,则不允许ld启动其执行的第二步
2.计算相对于所有较早st的ld有效地址来维持程序顺序

这两个限制共同确保了对于访问早期st所写入的存储位置的任何ld都无法执行存储访问,除非这个st已写入数据。 实际上,某些推测处理器在发生此类RAW危害时,会直接将存储中的值旁路到负载中。 另一种方法是使用值预测的形式来预测潜在的冲突。我们将在3.9节中对此进行考虑。

尽管这种对推测执行的解释集中在浮点上,但是这些技术很容易扩展到整数寄存器和功能单元。实际上,由于此类程序倾向于具有分支行为难以预测的代码,因此在整数程序中进行推测可能更为有用。 另外,通过允许每个时钟进行多个指令发出和提交,这些技术可以扩展为在多issue处理器中工作。 实际上,在这样的处理器中推测可能是最有趣的,因为如果技术要求不高,那么在编译器的协助下可以在基本块内实现足够多的ILP。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值