超标量和流水线有什么区别?

47

看起来似乎是一个非常简单的问题,但我在查看一些关于两种方法的PPT后还是提出了这个问题。

两种方法都可以增加指令吞吐量。超标量几乎总是利用流水线技术。超标量拥有多个执行单元,而流水线也是如此。或者我理解错了吗?


4
我删除了所有与问题无关的评论,但并没有留下任何评论。请大家保持礼貌。 - Marc Gravell
好主意。否则,一个完全好的问题可能会被关闭为“主观和争论性”! - RCIX
5个回答

69
超标量设计意味着处理器能够在单个时钟周期内发出多条指令,并具有执行指令的冗余设施。需要注意的是,这是在单个核心内进行的——多核处理是不同的。 流水线技术将指令分为步骤,由于每个步骤在处理器的不同部分执行,所以多个指令可以在不同的“阶段”中每个时钟周期执行。
它们几乎总是一起使用。维基百科上的这张图片展示了两个概念的使用情况,因为这些概念最好用图形方式解释:

Superscalar/pipelining in use

这里,在五级流水线中同时执行两个指令。


进一步分解,鉴于您最近的编辑:
在上面的示例中,指令经过5个阶段进行"执行"。 这些是IF(指令获取),ID(指令解码),EX(执行),MEM(更新内存)和WB(写回高速缓存)。
在非常简单的处理器设计中,每个时钟都会完成不同的阶段,因此我们将拥有:
1. IF 2. ID 3. EX 4. MEM 5. WB
这将在五个时钟中执行一条指令。 如果我们添加了一个多余的执行单元并引入超标量设计,则会得到以下结果,用于两个指令A和B:
1. IF(A)IF(B) 2. ID(A)ID(B) 3. EX(A)EX(B) 4. MEM(A)MEM(B) 5. WB(A)WB(B)
在五个时钟中执行两条指令-理论上最大增益100%。
流水线允许同时执行各个部分,因此我们最终会得到类似以下内容的东西(用于十个指令A到J):
  1. 如果(A),那么如果(B)
  2. 标识(A),标识(B),如果(C),那么如果(D)
  3. 扩展(A),扩展(B),标识(C),标识(D),如果(E),那么如果(F)
  4. 存储器(A),存储器(B),扩展(C),扩展(D),标识(E),标识(F),如果(G),那么如果(H)
  5. 写回(A),写回(B),存储器(C),存储器(D),扩展(E),扩展(F),标识(G),标识(H),如果(I),那么如果(J)
  6. 写回(C),写回(D),存储器(E),存储器(F),扩展(G),扩展(H),标识(I),标识(J)
  7. 写回(E),写回(F),存储器(G),存储器(H),扩展(I),扩展(J)
  8. 写回(G),写回(H),存储器(I),存储器(J)
  9. 写回(I),写回(J)

在九个时钟周期内,我们执行了十条指令——你可以看到流水线确实加速了事情的进展。这是对示例图的解释,而不是它在实际领域中的实现(那是黑魔法)。

维基百科上的SuperscalarInstruction pipeline文章非常好。


4
它们主要一起使用是因为两种技术都可用,都是好的想法,并且现代过程制造技术使其成为可能。具有流水线但不是超标量技术的显著芯片包括英特尔i486和一些早期的ARM、MIPS CPU以及第一款Alpha处理器。 - Paul Hsieh
2
第一个“execute”应该是一个“issue”,然后你可以使用“execute”代替“do”。这就是Henessy&Patterson书中所称的阶段。 - yeyeyerman
1
@yeyeyerman:感谢您的反馈,我已经修正了答案。我对材料上的文本没有太多接触,所以请原谅我的疏忽。 - Jed Smith
“冗余”意味着“多余”,“不必要”,或者“在其他组件发生故障的情况下包含的,但并非严格必要的”。但是,在超标量处理器上,功能单元甚至不需要提供重叠功能(例如,在您拥有单独的分支单元、ALU和内存单元的情况下)。 - Wandering Logic
如果我理解正确的话,那么这意味着维基百科的例子正在使用流水线进行向量处理,当它可以每个周期发出不同的指令?我说的是两个指令执行单元。请参见此处 - http://imgur.com/gPsVAWY - goelakash
那么,单核超标量处理器和多核标量处理器之间有什么区别呢? - lodhb

37
很久以前,CPU一次只执行一个机器指令。只有当它完全执行完成后,CPU才会从内存(或后来的指令缓存)中获取下一个指令。
最终,有人注意到这意味着大部分时间CPU都在闲置,因为有几个执行子单元(例如指令解码器、整数算术单元和FP算术单元等),执行一条指令只能让其中一个保持繁忙。
因此,“简单”的流水线技术应运而生:一旦一条指令完成解码并进入下一个执行子单元,为什么不提前获取和解码下一条指令呢?如果你有10个这样的“阶段”,那么通过让每个阶段处理不同的指令,理论上可以将指令吞吐量提高十倍,而无需增加CPU时钟!当然,这仅在代码中没有条件跳转时才能完美地运行(这导致了需要特殊处理条件跳转的额外工作)。
后来,随着摩尔定律的持续正确性超出预期,CPU制造商发现自己拥有越来越多的晶体管可供利用,并想到“为什么只有一个执行子单元?”因此,具有多个执行子单元能够并行执行相同操作的超标量CPU诞生了,而CPU设计变得更加复杂,以便在这些完全并行的单元之间分配指令,并确保结果与顺序执行的结果相同。

8
这样的回答应该能够结束有关在Stack Overflow上提出这类问题价值的辩论。 - Alex Xander
2
很久很久以前,在一个遥远的世界? - Jed Smith
1
我会点赞,但是超标量CPU的描述是不正确的。你正在描述一个向量处理器,而超标量处理器略有不同。 - Wedge
@MichaelBorgwardt:我认为这个说法有问题:“如果你有10个这样的“阶段”,那么通过让每个阶段处理不同的指令,理论上可以将指令吞吐量增加十倍,而不需要增加CPU时钟!”如果你从非流水线到流水线版本不改变(减少近10倍)CPU时钟,那么流水线如何在总体执行时间上受益呢?只有当每个阶段运行速度快10倍时,它才会受益。 - nurabha
1
在实践中,一些形式的流水线早期就已经完成了,真正的问题是给定处理器的流水线有多深。我认为 Pentium IV 有一个相当极端的流水线,有40多个阶段。 - Michael Borgwardt
显示剩余9条评论

14
  • iron the shirt, dry the pants
  • fold the shirt, iron the pants
  • put the shirt back on the rack, fold the pants
  • take the coat from the rack
  • wash the coat, while it's washing...
  • iron the pants
  • dry the coat, while it's drying...
  • fold the coat
  • put the pants back on the rack, put the coat back on the rack
  • As you can see, by taking advantage of the downtime during each step, the new attendant is able to finish all of the laundry much more quickly and efficiently than the old one.

  • 熨衣服,晾干裤子
  • 叠衬衫,(从衣架上拿下外套)
  • 把衬衫放回衣架上,叠裤子(洗外套)
  • 把裤子重新挂回衣架上(晾干外套)
  • (熨烫外套)
  • (把外套放回衣架上)
  • 这就是流水线技术。将不相关的活动顺序安排在一起以同时使用不同的组件。通过同时保持尽可能多的不同组件的活跃状态,可以最大程度地提高效率并加快执行时间,在这种情况下可以将16个“循环”缩减为9个,“速度提升超过40��”。

    现在,这家小洗衣店开始赚更多的钱,因为他们能够更快地工作,所以老板买了一台额外的洗衣机、烘干机、熨衣板、叠衣站,甚至雇了另一个服务员。现在事情变得更快了,不是以上的步骤,而是:

  • 从衣架上拿下衬衫,从衣架上拿下裤子
  • 洗衬衫,洗裤子(从衣架上拿下外套)
  • 晾干衬衫,晾干裤子(洗外套)
  • 熨烫衬衫,叠裤子(晾干外套)
  • 叠衬衫,把裤子重新挂回衣架上(熨烫外套)
  • 把衬衫放回衣架上,(把外套放回衣架上)
  • 这就是超标量设计。多个子组件可以同时执行相同任务,但处理器会决定如何执行。在这种情况下,它导致了近50%的速度提升(在18个“循环”内,新结构可以运行3次此“程序”的迭代,而旧结构仅能运行2次)。

    旧的处理器(如386或486)是简单的标量处理器,它们按照接收到指令的顺序一个接一个地执行。自PowerPC / Pentium以来的现代消费级处理器是流水线和超标量的。Core2 CPU能够运行为486编译的相同代码,并利用指令级并行性,因为它包含自己的内部逻辑,分析机器代码并确定如何重新排序和运行它(可以并行运行什么,不能并行运行什么等)。这就是超标量设计的精髓,也是为什么它如此实用。

    与此相反,向量并行处理器一次对多个数据块(向量)进行操作。因此,向量处理器不仅只是将x和y相加,而是将x0、x1、x2与y0、y1、y2相加(最终得到z0、z1、z2)。但这种设计的问题在于它与处理器的特定并行度紧密耦合。如果在向量处理器上运行标量代码(假设您可以这样做),则无法使用向量并行化的优势,因为需要明确使用,同样,如果您要利用具有更多并行处理单元的新型向量处理器(例如,能够添加12个数字的向量而不仅仅是3个),则需要重新编译代码。向量处理器设计在最早期的超级计算机中很受欢迎,因为它们易于设计,并且科学和工程中有大量具有自然并行性的问题。

    超标量处理器也可以具有执行推测的能力。处理器可以猜测分支前面的代码是否已经完成执行,而不是让处理单元空闲等待分支完成执行后再进行分支。当先前的代码执行到分支点时,处理器可以将实际的分支与分支猜测进行比较,如果猜测正确,则继续执行(已经比等待执行更快);或者,如果猜测错误,则无效化推测执行结果并运行正确分支的代码。


    6
    流水线是汽车公司在制造汽车时所采用的一种方法。他们将组装汽车的过程分解为不同的阶段,并由不同的人员在装配线上的不同点执行这些阶段。其最终结果是汽车的制造速度正好等于最慢的阶段的速度。
    在CPU中,流水线过程完全相同。"指令"被分解成各个执行阶段,通常是1.获取指令,2.获取操作数(读取寄存器或内存值),3.执行计算,4.写入结果(到内存或寄存器)。其中最慢的可能是计算部分,在这种情况下,指令通过此流水线的整体吞吐量速度就是计算部分的速度(就像其他部分是“免费”的一样)。
    微处理器中的超标量是指能够同时并行运行单个执行流中的多个指令。因此,如果汽车公司运行两条装配线,那么显然他们可以生产两倍的汽车。但是,如果将序列号放在最后一个阶段并且必须由单个人完成,则他们必须在两个流水线之间交替,并保证他们可以在慢est阶段的一半时间内完成每个流水线,以避免成为最慢的阶段。
    微处理器中的超标量类似,但通常有更多限制。因此,指令获取阶段通常会在其阶段内产生多个指令 - 这就是使微处理器中的超标量成为可能的原因。然后将有两个获取阶段、两个执行阶段和两个写回阶段。这显然可以推广到不止两个流水线。
    这些都很好,但从正确执行的角度来看,如果盲目地执行这些技术,两种技术都可能导致问题。为了正确执行程序,假设指令按顺序完全执行。如果两个连续的指令具有相互依赖的计算或使用相同的寄存器,则可能会出现问题。后面的指令需要等待前一个指令的写回完成,然后才能执行操作数获取阶段。因此,您需要在第二个指令执行之前将其停滞两个阶段,这将破坏这些技术最初所获得的目的。
    有许多技术可用于减少需要停滞的问题,但有点复杂,我将列举它们:1.寄存器转发(也包括存储到加载转发)2.寄存器重命名3.记分牌4.乱序执行5.具有回滚(和退役)的投机执行。所有现代CPU几乎都使用所有这些技术来实现超标量和流水线。然而,这些技术在处理器中的管道数量方面往往会出现递减收益,直到停滞不可避免。实际上,没有CPU制造商在单个核心中制造超过4个流水线。

    多核与这些技术没有任何关系。它基本上是将两个微处理器组合在一起,在单个芯片上实现对称多处理,并仅共享那些有意义的组件(通常是L3缓存和I/O)。然而,英特尔所谓的“超线程”技术是一种试图在单个核心的超标量框架内虚拟实现多核语义的方法。因此,单个微体系结构包含两个(或更多)虚拟核心的寄存器,并从两个(或更多)不同的执行流中提取指令,但从一个公共的超标量系统中执行。这个想法是,因为寄存器不能相互干扰,会倾向于有更多的并行性,从而减少停顿。因此,与其仅以一半的速度执行两个虚拟核心执行流,不如由于总体停顿的减少而更好。这似乎表明英特尔可以增加管道的数量。然而,这种技术在实际实现中被发现有些不足。尽管如此,由于它是超标量技术的一部分,我还是提到了它。


    2

    流水线是在同一周期内同时执行多个指令不同阶段的技术。它基于将指令处理分为多个阶段,并为每个阶段提供专门的单元和用于存储中间结果的寄存器。

    超标量是将多个指令(或微指令)分派到CPU中的多个执行单元进行执行的技术。因此,它基于CPU中存在冗余单元。

    当然,这些方法可以相互补充。


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接