我遗漏了一些基本的东西 . CPU流水线:在基本级别,为什么指令需要不同数量的时钟周期才能完成,为什么某些指令在多级CPU中只需要1个周期?
除了明显的“不同指令需要完成不同的工作量”之外,请听我说...
考虑一个带有大约14级流水线的i7 . 这需要14个时钟周期才能完成一次运行 . AFAIK,这应该意味着整个管道的延迟为14个时钟 . 然而事实并非如此 .
XOR在1个周期内完成,延迟为1个周期,表明它不会经历所有14个阶段 . BSR的延迟为3个周期,但每个周期的吞吐量为1 . AAM的延迟为20个周期(比阶段计数多),吞吐量为8个(在Ivy Bridge上) .
某些指令不能在每个时钟发出,但完成时间不到14个 .
我知道多个执行单元 . 我不明白延迟和吞吐量方面的指令长度如何与pipline阶段的数量相关 .
2 回答
因为我们感兴趣的是指令之间的速度,而不是单个指令的开始结束时间 .
那么这就是为什么不同的指令有不同的延迟的关键答案 .
这是正确的,尽管这不是一个特别有意义的数字 . 例如,为什么我们要关心CPU在完成指令之前需要多长时间?这基本上没有效果 .
这只是一堆误解 . XOR将一个延迟周期引入依赖关系链 . 也就是说,如果我执行12条指令,每条指令修改前一条指令的值,然后添加一条XOR作为第13条指令,则需要多一个周期 . 这就是延迟意味着什么 .
对 . 所以?
他们没有 . 为什么要连接?假设管道开始处有14个额外的阶段 . 为什么这会影响延迟或吞吐量?这只意味着所有事情都发生在14个时钟周期之后,但仍然保持相同的速度 . (虽然它可能会影响错误预测的分支和其他事情的成本 . )
我认为现有答案中缺少的是“旁路”或“转发”数据路径的存在 . 为简单起见,我们坚持使用MIPS 5级流水线 . 每个指令从出生到死亡需要5个周期 - 获取,解码,执行,记忆,回写 . 这就是处理单个指令所需的时间 .
您想知道的是一条指令将其结果移交给依赖指令需要多长时间 . 假设您有两个连续的ADD指令,并且通过R1存在依赖关系:
如果没有转发路径,我们必须将第二条指令停顿多个周期(2或3,取决于写回的工作方式),这样第一条指令就可以将其结果存储到寄存器文件中,然后第二条指令读取为在解码阶段输入 .
但是,存在允许从管道中挑选出有效结果(但尚未写回的结果)的转发路径 . 所以我们假设第一个ADD在解码中从寄存器文件中获取所有输入 . 第二个将从寄存器文件中获取R5,但它会在执行阶段之后将R1从流水线寄存器中移出 . 换句话说,我们将ALU的输出在一个循环后路由回输入 .
无序处理器无处不在地使用转发 . 它们将具有许多不同的功能单元,这些功能单元具有许多不同的延迟 . 例如,ADD和AND通常需要一个周期(TO DO THE MATH,将所有流水线阶段放在前后),MUL将采用4个,浮点运算需要很多周期,内存访问具有可变延迟(由于缓存未命中)等
通过使用转发,我们可以限制一个关键路径指示执行单元的延迟,而其他一切(获取,解码,退出),它离开关键路径 . 指令被解码并转储到指令队列中,等待其输入由其他执行指令产生 . 当满足指令的依赖性时,它就可以开始执行 .
让我们考虑这个例子
我将尝试绘制一个时间轴,通过管道显示这些指令的流程 .
键:
因此,如您所见,乘法指令的总生命周期为9个周期 . 但是执行MUL和ADD时存在重叠,因为处理器是流水线的 . 当ADD进入IQ时,它必须等待其输入(R1),同样依赖于ADD结果(R2)的AND也是如此 . 我们关心的不是MUL总共存在多久,而是任何依赖指令必须等待多长时间 . 这是它的有效延迟,即4个周期 . 如您所见,ADD执行后,依赖AND可以在下一个周期执行,这也是由于转发 .