我理解instruction pipelining的基本原则。
我还得到一些指令可能需要更长时间才能执行(cycles per instruction)。
但我没有得到两者之间的联系。
我看到的所有管道图似乎都有完美的"说明,它们都有相同的长度(循环次数)。
但是如果第一条指令需要5个周期,第二条指令需要3个周期呢? cpu是否会停顿2个周期?
这个摊位会被称为bubble吗?或者这与hazards和数据依赖性不同?
另外,指令的长度(以字节为单位)是否有任何影响?
答案 0 :(得分:3)
你提出了很多关于你问题的事情,所以我会花2美分试着让它变得更加清晰。让我们看一个有序的MIPS架构作为一个例子 - 除了可变长度指令外,它还包含你提到的所有内容。
许多MIPS CPU都有5级流水线,其阶段为:IF -> ID -> EX -> MEM -> WB
。 (https://en.wikipedia.org/wiki/Classic_RISC_pipeline)。让我们首先看一下这些指令,其中每个阶段通常需要一个时钟周期(例如,在缓存未命中时可能不是这种情况)。例如,SW(存储字到存储器),BNEZ(分支不为零)和ADD(添加两个寄存器并存储到寄存器)。并非所有这些说明在所有管道阶段都有用。例如,SW在WB阶段没有工作要做,BNEZ可以早在ID阶段完成(这是最早的目标地址可以计算),而ADD在MEM阶段没有工作。
无论如何,这些说明中的每一条都将经历管道的每个阶段,即使它们中的某些部分没有工作。该指令将占用一个给定的阶段,但不会进行实际的工作(即没有结果写入WB阶段的寄存器用于SW指令)。换句话说,在这种情况下不会有摊位。
切换到更复杂的指令,其EX阶段可能需要数十个周期,如MUL或DIV。这里的事情变得更加棘手。现在,指令可以按顺序完成,即使它们总是按顺序提取(意味着现在可以WAW hazards)。请看以下示例:
MUL R1, R10, R11
ADD R2, R5, R6
首先获取MUL并在ADD之前到达EX阶段,但是在MUL的EX阶段运行超过10个时钟周期之前ADD将完成。但是,管道不会在任何时候停止,因为这个序列中不存在危险 - RAW和WAW都不可能发生危险。再举一个例子:
MUL R1, R10, R11
ADD R1, R5, R6
现在MUL和ADD都写入相同的寄存器。由于ADD将比MUL早完成,它将完成WB并写入其结果。稍后,MUL将执行相同的操作,R1最终会出现错误(旧)值。这是需要管道 停止 的地方。解决此问题的一种方法是防止ADD发出(从ID移到EX阶段),直到MUL进入MEM阶段。这是通过冻结或停止管道来完成的。引入浮点运算会导致类似的问题。
我通过触及固定长度与可变长度指令格式的主题来完成我的回答(即使你没有明确要求它)。 MIPS(和大多数RISC)CPU具有固定长度编码。这极大地简化了CPU流水线的实现,因为指令可以在一个周期内被解码并且输入寄存器被读取(假设寄存器位置以给定的指令格式固定,这对于MIPS是正确的)。此外,由于指令总是具有相同的长度,因此简化了读取操作,因此无需开始解码指令以查找其长度。
当然存在一些缺点:生成紧凑二进制文件的可能性降低,这导致程序更大,从而导致较差的缓存性能。此外,内存流量增加以及从内存读取/写入更多字节数据,这对于节能平台而言可能非常重要。
这一优势导致一些RISC架构定义了16位指令长度模式(MIPS16或ARM Thumb),甚至可变长度指令集(ARM Thumb2具有16位和32位指令)。与x86不同,Thumb2的设计使得快速确定指令长度变得容易,因此CPU仍然很容易解码。
这些压缩的ISA通常需要更多指令来实现相同的程序,但如果代码获取比管道中的指令吞吐量更多地成为瓶颈,则占用更少的总空间并且运行得更快。 (小/不存在的指令高速缓存,和/或从嵌入式CPU中的ROM读取)。
答案 1 :(得分:2)
实际上比你想象的要复杂一点。
对于一个CPU不执行指令,它会执行uops,其次它可以不按顺序执行uops。
<强>微指令强>
简单指令转换为单个uop,复杂指令分为多个uop。 CPU有一个uop缓存,可以保留最后一个(例如1024个)uop。 uops比完整指令更相似,因此在管道中配对更好。
无序执行
如果CPU需要等待计算结果,它会查找与前一条指令无关的uops并执行这些操作。
为了允许OoO执行,CPU具有寄存器文件,该寄存器文件具有比程序员可用的寄存器多得多的寄存器(例如256个通用寄存器)。它可以用它作为便笺簿来存储中间结果
所有执行的指令都进入退休缓冲区,其中结果以原始顺序输出。
<强>缓冲器强>
除此之外,档位问题由缓冲区确定
指令是以推测方式获取的,并且位于缓冲区中等待解码。
恒定时间解码
X86 / X64以其复杂的解码而臭名昭着。 AMD和英特尔都通过在解码问题上投入大量的硅来解决这个问题,因此他们的cpus可以解码每个周期的恒定字节数,与指令复杂性无关。指令的长度并不重要,因为时间关键代码(紧密循环)是从uop-cache执行的,不需要解码。此外,解码通常是超尺寸的,因此几乎肯定不是瓶颈。
更多阶段
现代CPU有14个或更多阶段,而不是你想象的4个阶段。
例如,参见AMD禅宗架构的展示:https://www.extremetech.com/computing/234354-a-state-of-zen-amd-unveils-new-architectural-details-on-its-latest-cpu-core
因此,除了管道之外,还有很多其他流程可以实施,其中包括防止停滞和填充气泡的过程。
在实践中,现代处理器在配对具有不同延迟的指令时不会受到影响。低延迟uops的使用已经在很大程度上消除了这个问题。
<强>危险强>
您链接的维基百科文章很好地解释了它。现代CPU使用Tomasulo's algorithm with register renaming来防止气泡。