指令管线化(英语:Instruction pipeline)是为了让计算机和其它数位电子装置能够加速指令的通过速度(单位时间内被执行的指令数量)而设计的技术。

RISC机器的五层管线示意图(IF:读取指令,ID:指令解码,EX:执行,MEM:记忆体存取,WB:写回暂存器)

管线在处理器的内部被组织成层级,各个层级的管线能半独立地单独运作。每一个层级都被管理并且链接到一条“链”,因而每个层级的输出被送到其它层级直至任务完成。 处理器的这种组织方式能使总体的处理时间显著缩短。

未管线化的架构产生的效率低,因为有些CPU的模组在其他模组执行时是闲置的。管线化虽并不会完全消除CPU的闲置时间,但是能够让这些模组并行运作而大幅提升程式执行的效率。差不多有些类似流水线工厂的概念。

但并不是所有的指令都是独立的。在一条简单的管线中,完成一个指令可能需要5层。如右图所示,要在最佳性能下运算,当第一个指令被执行时,这个管线需要运行随后4条独立的指令。可是,如果随后4条指令依赖于第一条指令的输出,管线控制逻辑器,就必须插入延迟时脉周期到管线内,直到依赖被满足。而转发技术能显著减少延时。凭借多个层,虽然管线化在理论上能提高效能,优胜于无管线的内核(假设时脉也因应层的数量按比例增加),但事实上,许多指令码设计中并不会考虑到理想的执行。

简介

Thumb
RISC机器的五层管线示意图

管线化是假设程式执行时有一连串的指令要被执行(垂直座标i是指令集,水平座标表时间t)。绝大多数当代的CPU都是利用时脉驱动。

而CPU是由内部的逻辑闸正反器组成。当受到时脉触发时,正反器得到新的数值,并且逻辑闸需要一段时间来解析出新的数值,而当受到下一个时脉触发时正反器又得到新的数值,以此类推。而借由逻辑闸分散成很多小区块,再让正反器链接这些小区块组,使逻辑闸输出正确数值的时间延迟得以减少,这样一来就可以减少指令执行所需要的周期。

举例来说,典型的RISC管线被分解成五个阶段,每个阶段之间使用正反器链接。

  1. 读取指令
  2. 指令解码与读取暂存器
  3. 执行
  4. 记忆体存取
  5. 写回暂存器

优缺点

并非在所有情况下管线技术都起作用。可能有一些缺点。如果一条指令管线能够在每一个时脉周期接纳一条新的指令,被称为完整管线化(fully pipelined)。因管线中的指令需要延迟处理而要等待数个时脉周期,被称为非完整管线化。

当一名程序员(或者组合者/编译者)编写组合代码(或者汇编码)时,他们会假定每个指令是循序执行的。而这个假设会使管线化无效。当此现象发生后程式会表现的不正常,而此现象就是危害。不过目前有提供几种技术来解决这些危害像是转发延迟等。

优点

  1. 减少了处理器执行指令所需要的时脉周期,在通常情况下增加了指令的输入频率(issue-rate)。
  2. 一些集成电路(combinational circuits),例如加法器(adders)或者乘法器(multipliers),通过添加更多的环路(circuitry)使其工作得更快。如果以管线化替代,能相对地减少环路。

缺点

  1. 非管线化的处理器每次(at a time)只执行一个指令。防止分支延时(事实上,每个分支都会产生延时)和串行指令被并行执行产生的问题。设计比较简单和较低生产成本。
  2. 在执行相同的指令时,非管线化处理器的指令传输延迟时间(The instruction latency)比管线化处理器明显较短。这是因为管线化的处理器必须在数据路径(data path)中添加额外正反器(flip-flops)。
  3. 非管线化处理器有固定指令位宽(a stable instruction bandwidth)。管线化处理器的性能更难以预测,并且不同的程序之间的变化(vary)可能更大。

示例

一般的管线

Thumb
一般的四层管线架构;不同的颜色格表示不同的指令

右图是一般有4层管线的示意图:

  1. 读取指令(Fetch)
  2. 指令解码(Decode)
  3. 执行指令(Execute)
  4. 写回执行结果(Write-back)

上方的大灰色格是一连串未执行的指令;下方的大灰色格则是已执行完成的指令;中间的大白色格则是管线。

执行顺序如以下列表所示:

More information 时序, 执行情况 ...
时序 执行情况
0 四条指令等待执行
1
  • 记忆体(memory)中读取绿色指令
2
  • 绿色指令被解码
  • 从主存储器中读取紫色指令
3
  • 绿色指令被执行(事实上运算已经开始(performed))
  • 紫色指令被解码
  • 从主存储器中读取蓝色指令
4
  • 绿色指令的运算结果被写回到寄存器(register)或者主存储器
  • 紫色指令被执行
  • 蓝色指令被解码
  • 从主存储器中读取红色指令
5
  • 绿色指令被执行完毕
  • 紫色指令的运算结果被写回到寄存器或者主存储器
  • 蓝色指令被执行
  • 红色指令被解码
6
  • 紫色指令被执行完毕
  • 蓝色指令的运算结果被写回到寄存器或者主存储器
  • 红色指令被执行
7
  • 蓝色指令被执行完毕
  • 红色指令的运算结果被写回到寄存器或者主存储器
8
  • 红色指令被执行完毕
9 所有指令皆执行完毕
Close

汽泡

Thumb
一个气泡在编号为3的时脉周期中,指令执行被延迟

指令执行中产生一个“打嗝”(hiccup),在管线中生成一个没有实效的气泡。

如右图,在编号为2的时脉周期中,紫色指令的读取被延迟,并且在编号为3的时脉周期中解码层也产生了一个气泡。所有在紫色指令之后的指令都被延迟执行,而在其之前已经执行了的指令则不受影响。

由于气泡使指令执行延迟了一个时脉周期,完成全部4条指令的执行共需要8个时脉周期。

而气泡处对指令的读取、解码、执行与写回都没有实质影响。这可以使用nop代码来完成。

复杂化

很多处理器的管线深度到5层、7层、10层,甚至31层(像是Intel Pentium 4 Prescott)。Xelerator X10q甚至有多于1000层的管线深度[1]页面存档备份,存于互联网档案馆)。

More information 微架构 (Microarchitecture), 管线层数 (Pipeline stages) ...
微架构

(Microarchitecture)

管线层数

(Pipeline stages)

Sony Cell 23
IBM PowerPC 7 17
IBM Xenon 19
AMD Athlon 10
AMD Athlon XP 11
AMD Athlon 64 12
AMD Phenom 12
AMD Opteron 15
ARM7TDMI (-S) 3
ARM7EJ-S 5
ARM810 5
ARM9TDMI 5
ARM1020E 6
XScale PXA210/PXA250 7
ARM1136J (F)-S 8
ARM1156T2 (F)-S 9
ARM Cortex-A5 8
ARM Cortex-A8 13
AVR32 AP7 7
AVR32 UC3 3
DLX 5
Intel P5Pentium 5
Intel P6Pentium Pro 14
Intel P6(Pentium III 10
Intel NetBurst(Willamette) 20
Intel NetBurst(Northwood) 20
Intel NetBurst(Prescott) 31
Intel NetBurst(Cedar Mill) 31
Intel Core 14
Intel Atom 16
LatticeMico32 6
R4000 8
StrongARM SA-110 5
SuperH SH2 5
SuperH SH2A 5
SuperH SH4 5
SuperH SH4A 7
UltraSPARC 9
UltraSPARC T1 6
UltraSPARC T2 8
WinChip 4
LC2200 32 bit 5
Close

当程式出现分支将不利于过深管线,整条管线将会无效化。为了减轻此状况,分支预测就变的重要。如果分支预测错误,也能够借由自行结束预测来避免加速恶化效率。在某些运用上,像是超级电脑运算,为了能够将超长管线的运算优势凸显出来,会特地将程式写的极少分支化来避免预测失败,而且深度的管线化主要是为了能降低每个时脉执行的指令量而设计。当程式经常出现分支,把分支重新排序(像是将更为需要的指令提早放入管线中)而将明显的降低损失的速度以避免将分支“冲垮”。像是gcov程式能够使用一种覆盖率检查的技术检查特定分支的执行频率,但是这种检查法经常是最佳化的最后手段。处理能力高的管线会因为很多分支的程式而降低效率,这是因为处理器不知道下一个要读取的指令是甚么,而需要等待完成分支指令而让管线清空。处理完分支之后,下一个指令就要经过所有管线,直到整个指令集的结果出现,而处理器才会再继续执行。而在极端的状况下,管线化处理器的效能理论上可能会与未管线化处理器一致,甚至是每层管线都在待命状态,而且指令经常在管线之中跑来跑去时的效能比较差一些。

由于指令管线化,处理器读取机器码时并不会立即执行。因为如此,在很接近的地方执行更新机器码的动作就可能无法作用,因为这些机器码已经进入预读输入队列内。指令快取又会让此现象更加恶化。不过这只会在能够自我变更的程式出现此现象。

范例

范例一

一个典型的加法指令可能会写成像ADD A, B, C,而中央处理器(CPU)会将记忆体(Memory)内A位置与B位置的数值相加后放到C位置。在管线化处理器内,管线控制器会将这个指令分拆成一连串微指令:

LOAD R1, A
LOAD R2, B 
ADD R3, R1, R2
STORE R3, C
LOAD next instruction

R1, R2R3是CPU内的暂存器(register是CPU里面能够快速存取的暂存记忆体)。主存储器内标注为A位置和B位置之存储单元中的数值被载入(或称复制)到暂存器R1和R2中,然后送到加法器中相加,结果输出到暂存器R3中,R3中的数值再被存储到主存储器内标注为C位置的存储单元。

而且在非管线化的例子,开始驱动加法动作到完成的时间是不变的。

在这个范例中的管线分为3层:载入,执行,存储。每一步被称为管线层(或称管线阶段,pipeline stages)。

在非管线化处理器中,同一时间只允许一个层运作,所以必须等待指令执行完毕才能开始执行下一条指令。在管线化处理器中,所有的层能在同一时间处理不同的指令。当一条指令在执行层,另外一条指令在解码层,第三条指令在读取层。

管线没有减少执行指令所花费的时间;它增加了在同一时间被处理的指令数量,并且减少了完成指令之间的延迟。随着处理器中管线层的数量增加,能在同一时间被处理的指令数量也相应增加,也减少了指令等待处理所产生的延迟。现在生产的微处理器至少有2层管线。[来源请求]Atmel AVRPIC微控制器都有2层管线)Intel Pentium 4处理器有20层管线。

范例二

以下表格具体列出3层管线理论:

More information 管线层(Stage), 说明(Description) ...
管线层(Stage) 说明(Description)
读取(Load) 从主存储器中读取指令
执行(Execute) 执行指令
存储(Store) 将执行结果存储到主存储器和/或者暂存器
Close

组合语言表示将会被执行的指令列表:

	LOAD  A, #40      ;讀取40載入A內
	MOVE  B, A        ;將A內的数据移动到B內
	ADD   B, #20      ;將B內的數據與20相加
	STORE 0x300, B    ;將B內的數據儲存到地址為0x300的存儲器單元

代码的执行循序如下:

More information 读取, 执行 ...
第1周期
读取 执行 储存
LOAD
Close

从主存储器中读取LOAD指令。

More information 读取, 执行 ...
第2周期
读取 执行 储存
MOVE LOAD
Close

LOAD指令被执行,同时从主存储器中读取MOVE指令。

More information 读取, 执行 ...
第3周期
读取 执行 储存
ADD MOVE LOAD
Close

LOAD指令在存储层(Store stage),LOAD指令的执行结果#40(the number 40)将被存储到暂存器A。同时,MOVE指令被执行。MOVE指令必须等待LOAD指令执行完毕才能将暂存器A中的内容移动到暂存器B中。

More information 读取, 执行 ...
第4周期
读取 执行 储存
STORE ADD MOVE
Close

STORE指令被载入,同时MOVE指令执行完毕,并且ADD指令被执行。

注意! 有时候,一个指令会依赖于其他指令的执行结构(例如以上的MOVE指令)。当一个指令因为操作数而需引用一个特定的位置,读取(作为输入)或者写入(作为输入),执行那些指令的循序不同于程序原本的执行循序能导致冒险(hazards)。现时有机种技术用于预防危害,或者绕过(working around)它们。

参见

外部链接

Wikiwand in your browser!

Seamless Wikipedia browsing. On steroids.

Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.

Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.