指令管線化
指令流水线是现代微处理器、微控制器和CPU设计中使用的一种技术,用于提高其指令吞吐量(单位时间内可执行的指令数量)。
其主要思想是将指令微码所定义的CPU指令的处理过程(术语为"分割")划分为一系列独立的微操作步骤(也称为"微指令"、"微操作"或"微操作"),并在每个步骤的最后进行存储。这样,CPU的控制逻辑就可以以最慢一步的处理速度来处理指令,这比作为单步处理指令所需的时间快得多。
管道一词指的是每一步都承载着一条微指令(就像一滴水),每一步都与另一步相连(类比;类似于水管)。
大多数现代CPU都是由时钟驱动的。CPU内部由逻辑和存储器(倒装片)组成。当时钟信号到达时,翻转器存储其新的值,然后逻辑需要一段时间来解码翻转器的新值。然后下一个时钟脉冲到来,倒装片存储另一个值,以此类推。通过将逻辑分解成更小的片断,并在逻辑片断之间插入触发器,逻辑所需的时间(解码值到根据这些值产生有效的输出)就会减少。通过这种方式,可以减少时钟周期。
例如,将RISC流水线分成5个阶段,每个阶段之间有一组翻转器,如下所示。
- 指令获取
- 指令解码和寄存器获取
- 执行
- 内存访问
- 寄存器回写
带有流水线的处理器内部由各阶段(模块)组成,它们可以半独立地处理不同的微指令。每个阶段通过翻转器与下一阶段相连(就像一个"链"),这样该阶段的输出就是另一阶段的输入,直到完成处理指令的工作。这种处理器内部模块的组织方式减少了指令的整体处理时间。
非流水线架构的效率不高,因为一些CPU模块处于空闲状态,而另一个模块在指令周期内处于活跃状态。管道化并不能完全消除管道化CPU中的空闲时间,但使CPU模块并行工作可以提高指令吞吐量。
如果一个指令流水线每一个时钟周期都能接受一条新指令,就可以说它是完全流水线的。不完全流水线的流水线有等待周期,会延迟流水线的进度。
RISC机器中的基本五级流水线(IF=指令获取,ID=指令解码,EX=执行,MEM=内存访问,WB=寄存器回写)。纵轴是连续指令,横轴是时间。所以在绿柱中,最早的指令处于WB阶段,最晚的指令正在进行指令获取。
管道铺设的优势和劣势
管道化的优势。
- 缩短了处理器的周期时间;提高了指令吞吐量。管道化并没有减少完成一条指令所需的时间;相反,它增加了可以同时处理的指令数量("一次"),并减少了完成指令之间的延迟(称为"吞吐量")。
一个处理器拥有的流水线级数越多,它可以"一次"处理的指令就越多,完成指令之间的延迟就越少。目前生产的
每一个主流通用微处理器
都至少使用2级流水线,最高可达30或40级。 - 如果采用流水线方式,CPU算术逻辑单元可以设计得更快,但会更复杂。
- 理论上讲,流水线比未流水线的内核的性能提高了数倍(假设时钟频率也提高了同样的系数),而且代码非常适合流水线执行。
- 管道式CPU一般工作在比RAM时钟频率更高的时钟频率,(2008年的技术,RAM的工作频率比CPU的频率低)增加计算机的整体性能。
管道化的缺点。
管道化有很多缺点,虽然CPU和编译器设计者使用了很多技术来克服大部分缺点,下面是常见的缺点列表。
- 非管道式处理器的设计更简单,制造成本更低,非管道式处理器每次只执行一条指令。这样可以防止分支延迟(在Pipelining中,每个分支都会延迟)以及串行指令被并发执行时的问题。
- 在流水线处理器中,与非流水线处理器相比,模块之间插入翻转器会增加指令延迟。
- 非管道式处理器将有一个确定的指令吞吐量。管道式处理器的性能更难预测,不同程序的性能可能会有很大差异。
- 许多设计中包含了长达7、10、20、31甚至更多级的流水线,长流水线的一个缺点是当程序分支时,必须对整个流水线进行冲洗(清空)。当执行的代码中包含许多分支时,流水线的较高吞吐量就会落空:处理器无法预先知道下一条指令的读取位置,必须等待分支指令完成,使后面的流水线空着。通过根据之前的活动预测一个条件分支指令是否会分支,可以减少这个缺点。分支解决后,下一条指令必须在流水线上一路走过,其结果才会可用,处理器才会再次恢复"工作"。在这种极端情况下,流水线处理器的性能可能比非流水线处理器差。
- 不幸的是,并非所有的指令都是独立的。在一个简单的流水线中,完成一条指令可能需要5个阶段。为了以全性能运行,这个流水线需要在第一条指令完成的同时,运行4条后续的独立指令。这4条指令中的任何一条都可能依赖于第一条指令的输出,导致流水线控制逻辑等待并在流水线中插入一个停滞或浪费的时钟周期,直到依赖性得到解决。幸运的是,转发等技术可以大大减少需要停滞的情况。
- 当被修改的指令靠近正在执行的指令时,自修改程序可能无法在流水线架构上正常执行。这可能是由于指令可能已经在预取输入队列中,所以修改可能不会对即将执行的指令生效。指令缓存会使问题更加严重。
- 危害。当程序员(或编译器)编写汇编代码时,他们通常假设每条指令都是在下一条指令被执行之前执行的。当这种假设没有经过流水线验证时,就会导致程序的行为不正确,这种情况被称为危险。存在
各种解决危险或绕过的技术,如转发和延迟(通过插入一个停顿或浪费的时钟周期)。
例子
通用管道
右边是一个有四个阶段的通用管道。
- 领取
- 解码
- 执行
- 回写
顶部灰色框是等待执行的指令列表;底部灰色框是已经完成的指令列表;中间白色框是流水线。
执行情况如下:
时间 | 执行 |
0 | 有四条指令等待执行 |
1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | 所有的指令都会被执行 |
泡沫
当执行过程中发生"打嗝"(中断)时,会在流水线中产生一个"气泡",在这个气泡中没有任何有用的事情发生。在周期2中,紫色指令的获取被延迟,周期3中的解码阶段现在包含一个气泡。紫色指令后面的一切也被延迟,但紫色指令前面的一切继续执行。
显然,与上面的执行相比,气泡产生的总执行时间为8个时钟刻度,而不是7个时钟刻度。
气泡就像滞留(延迟),在这个过程中,获取、解码、执行和回写都不会发生任何有用的事情。它就像一个NOP(No OPeration的缩写)代码。
例1
一个典型的将两个数字相加的指令可能是ADD A
,
B
,
C
,它将在内存位置A和B中找到的值相加,然后将结果放在内存位置C中。在流水线处理器中,流水线控制器将把这分解成一系列类似的任务。
'R1'和'R2'是CPU中的寄存器。将存储在标有'A'和'B'的内存位置中的值加载(复制)到这些寄存器中,然后相加,结果存储在标有'C'的内存位置中。
在这个例子中,流水线有三个阶段--长期加载、执行和存储。每一个步骤都称为流水线阶段。
在非流水线处理器上,一次只能有一个阶段工作,所以在下一条指令开始之前,整个指令必须完成。在流水线处理器上,所有的阶段都可以同时工作在不同的指令上。所以当这条指令处于执行阶段时,第二条指令将处于解码阶段,第三条指令将处于获取阶段。
例二
为了更好地理解这个概念,我们可以看一个理论上的3阶段管道。
阶段 | 说明 |
负载 | 从内存中读取指令 |
执行 | 执行指令 |
商店 | 将结果存储在内存和/或寄存器中 |
和一个要执行的伪代码汇编列表。
这就是它的执行方式。
时钟1 | ||
负载 | 执行 | 商店 |
加载 |
|
|
LOAD指令是从内存中获取的。
时钟2 | ||
负载 | 执行 | 商店 |
移动 | 加载 |
|
LOAD指令被执行,而MOVE指令则从内存中获取。
时钟3 | ||
负载 | 执行 | 商店 |
ADD | 移动 | 加载 |
LOAD指令处于存储阶段,其结果(数字40)将被存储在寄存器A中,同时,MOVE指令正在执行。由于它必须将A的内容移入B中,所以必须等待LOAD指令的结束。
时钟4 | ||
负载 | 执行 | 商店 |
店铺 | ADD | 移动 |
STORE指令被加载,而MOVE指令正在整理,ADD正在计算。
以此类推。请注意,有时,一条指令会依赖于另一条指令的结果(比如我们的MOVE例子)。当有多条指令引用操作数的特定位置时,无论是读操作数(作为输入)还是写操作数(作为输出),按照与原程序顺序不同的顺序执行这些指令,都会导致危险情况的发生(如上所述)。
周期3中的一个气泡会延迟执行
通用的4级流水线;彩色方框代表相互独立的指令。
相关网页
- 管道
- 并行计算
- 指令级并行
问题和答案
问:什么是指令流水线?答:指令流水线是现代微处理器、微控制器和CPU设计中使用的一种技术,通过将CPU指令的处理分成一系列独立的步骤,并在每个步骤的末尾进行存储,从而提高其指令吞吐量。
问:流水线是如何工作的?
答:流水线的工作原理是将逻辑分解成更小的片段,并在逻辑片段之间插入触发器,这就减少了逻辑解码数值的时间,直到根据这些数值产生有效的输出。这允许更快的时钟周期。
问:流水线的一些例子是什么?
答:流水线的一个例子是RISC流水线,它被分成五个阶段,每个阶段之间有一组触发器。
问:流水线如何提高指令的吞吐量?
答:流水线通过允许CPU模块并行工作来增加指令吞吐量,从而减少指令周期内的空闲时间,增加整体处理时间。
问:是否每条流水线都是完全流水的?
答:不是,不是每条流水线都是完全流水的;有些流水线有等待周期,延迟流水线的进度。