计算机组成 -- Superscalar + VLIW

吞吐率

  1. 程序的CPU执行时间 = 指令数 × CPI × Clock Cycle Time
  2. CPI = Clock Per Instruction
  3. IPC = 1/CPI = Instruction Per Clock
    • 一个时钟周期内能够执行的指令数,代表了CPU的吞吐率
    • 最佳情况下,IPC只能到1
      • 无论做了哪些流水线层面的优化,即使做到了指令执行层面的乱序执行
      • CPU仍然只能在一个时钟周期内取一条指令!!
      • 无论指令后续无论优化得多好,一个时钟周期也只能执行一条指令,IPC只能是1
  4. Intel CPU或者ARM CPU,一般IPC能做到2以上

多发射 + 超标量

  1. 整数计算过程和浮点数的计算过程差异比较大
    • 整数计算和浮点数计算的电路,在CPU层面是分开
    • 一直到80386,CPU都是没有专门的浮点数计算的电路的,当时的浮点数计算,都是通过软件进行模拟
    • 在80386时代,Intel给386配了单独的387芯片,专门用来做浮点数运算
      • 386dx387浮点数计算芯片
      • 386sx:不带387浮点数计算芯片
  2. CPU会有多个ALU,在指令执行阶段,会采用乱序执行,这是由很多个功能单元(FU)并行(Parallel)进行的
    • 取指令(IF)和指令译码(ID)并不是并行的
  3. 增加硬件
    • 一次性从内存里面取出多条指令,然后分发给多个并行的指令译码器,进行译码,然后对应交给不同的功能单元去处理
      • 不同功能单元的流水线长度不同
      • 平时所说的14级流水线,通常指的是进行整数计算指令的流水线长度,如果是浮点数运算,实际的流水线长度会更长
    • 这样在一个时钟周期内,能完成多条指令,IPC可以大于1
    • 这种CPU设计,称为多发射(Mulitple Issue)或者超标量(Superscalar)
      • 多发射:在同一个时间,可能会同时多条指令发射到不同的译码器或者后续处理的流水线中去
      • 超标量:本来在一个时钟周期内,只能执行一个标量(Scalar)的计算,在多发射的情况下,能够同时进行多次计算
  4. Intel从Pentium时代,第一次引入超标量技术,整个CPU的性能上了一个台阶,对应的技术,一直沿用至今
    • 超标量技术和流水线技术,都是依赖于硬件层面能够检测到对应的指令的先后依赖关系,解决冒险问题,但使得电路变复杂

超长指令字

  1. 无论是乱序执行,还是超标量,在实际的硬件层面,实施起来都比较麻烦,因为CPU要解决依赖冲突的问题(即冒险问题)
    • 在指令执行之前,需要判断指令之间是否有依赖关系,如果有对应的依赖关系,指令就不能分发到执行阶段
    • 对于依赖关系的检测,使得CPU的电路变得更加复杂
  2. 程序的CPU执行时间 = 指令数 × CPI × Clock Cycle Time
    • 可以通过改进编译器来优化指令数这个指标
    • 诞生了超长指令字设计(Very Long Instruction Word,VLIW),尝试通过编译器来优化指令数CPI
  3. 乱序执行超标量的CPU架构里,指令的前后依赖关系,是由CPU内部的硬件电路来检测的
    • 到了超长指令字的架构里面,该工作交给了编译器来实现
  4. 编译器把没有依赖关系的代码位置进行交换,然后把多条连续的指令打包成一个指令包
  5. CPU运行时,不再是取一条指令,而是取出一个指令包译码解析整个指令包,解析出3条指令直接并行运行
  6. 使用超长指令字架构的CPU,同样采用的是流水线架构,一组指令,仍然要经历多个时钟周期
  7. 流水线停顿这件事情在超长指令字架构里面,很多时候也是由编译器实现的
    • 除了停下整个处理器流水线,超长指令字架构的CPU不能在某个时钟周期停顿一下,等待前面依赖的操作执行完成
    • 编译器需要在适当的位置插入NOP操作,直接在编译出来的机器码里面,就已经把流水线停顿这件事在软件层面处理了
  8. 安腾处理器失败的原因
    • 安腾处理器的指令集x86是不同的,原来x86上的所有程序都没办法在安腾处理器上运行,需要通过编译器重新编译
    • 安腾处理器的VLIW架构决定了如果安腾处理器需要提升并行度,就需要增加一个指令包里包含的指令数
      • 一旦从3变成6,虽然同为VLIW架构同样指令集的安腾处理器,程序也需要重新编译
      • 编译器判断依赖关系:3个指令以及由3个指令组成的指令包之间 -> 6个指令以及由6个指令组成的指令包之间
        • 编译器需要重新编译交换指令顺序插入NOP操作,才能满足条件
    • 不容易向前兼容,也不容易向后兼容
0%