目录

一、概述

二、性能指标和评估

三、pipeline

3.1 一个典型的五级流水线

3.2 pipeline stall

3.3 pipeline flush

3.4 forward

3.5 Dependencies

3.5.1 Control dependencies

3.5.2 Data dependencies

3.6 冒险

四、branch prediction

五、schedule

5.1 消除false dependencies

5.2 Tomasulo算法

5.2.1 ISSUE

5.2.2 dispatch

5.2.3 Broadcast


一、概述

最近看一个课程High Performance Computer Architecture收获不少,总结如下,算是对前篇文章的补充。本文试图将体系结构的脉络理清,不再像前篇那样,着眼于概念和术语解释层面,然而书写过程中深感功力不够,只能后续慢慢补充。

二、性能指标和评估

  • latecy
  • throughput

延迟和吞吐反相关

speedup = latency反比 = throughout正比

三、pipeline

计算机体系结构的发展就是一个不断演进的提升性能的过程。流水线的引入提高了指令吞吐量,3.1展示了一个经典的五级流水线,该技术使得CPI达到了1——每个cycle执行一条指令。然而,这仅仅是理想情况,事实上,由于程序指令中普遍存在着相关性,流水线不可避免的会产生气泡,导致pipeline stall,3.2 给出了一个pipeline stall的例子。3.3则给出一个跳转指令由于跳转目标不确定导致的pipeline flush的情况。为了避免pipeline stall,可以使用一种称为forward的技术,这将在3.4给予阐述,然而我们将看到,由于硬件设计上的一些限制,forward也不是万能的。

在3.5 我们分析流水线不能全速执行的原因,通过介绍数据相关,控制相关这两类相关,说明相关会造成流水线冒险,在后面的章节,将看到CPU是通过何种技术,来避免或是减少这些冒险的。

3.1 一个典型的五级流水线

  • 使用指标CPI(cycles per instruction)衡量指令吞吐,则在不使用流水线情况下,CPI=5
  • 考虑引入流水线的情况,在cycle 1起始,instruction 1流入流水线,在cycle 5结束,instruction 1 流出流水线,当流水线建立起来(对于5-stage 需要5个cycle),每一个cycle都有一条指令流出(完成),则CPI=1, 因此流水线提高了指令吞吐。需要注意的是,流水线并没有提高指令执行的latency——仍然是5cycle

3.2 pipeline stall

关注两条指令:

I1: LD R1, (R2)
I2: ADD R3, R1, 1

cycle 1,I1指令在EXE stage,计算load有效地址,I2指令在ID stage,读取R1的值,注意到该R1的值由于依赖I1指令的结果,因此在这个阶段取到的值并不正确!不能流入下一个stage

所以在cycle 2,I2指令仍在ID阶段,I1指令流进MEM阶段,因此产生了一个流水线stall(称为pipeline bubble),对应图中STALL1, I1 在MEM阶段仅将值加载到流水线寄存器中,因此I2仍不能获取R1的最新值,不能流入下一个stage

所以在cycle3,l2指令依然处于ID阶段,I1指令流入WB stage,因此产生新的stall,对应图中STALL2,I1在cycle的前半个周期将R1值回写,这样在后半个周期I2 读到最新的R1,这时指令可以流入下一个stage了(如果WB是全周期的,那么会产生新的STALL3,因为I2在该cycle中仍然无法得到正确的R1)

这之后,流水线可以正常的运行了

可以看到流水线stall阻止了当前核后续指令的流动,使CPI增加。

3.3 pipeline flush

如果指令是一条跳转指令,由于在EXE阶段才能确定JUMP跳转的地址,因此在EXE stage,IF, ID的指令可能与跳转目标不一致,所以此时流水线flush掉EXE之前的所有指令(如上图两个删除线),这样,随着流水线的进行,产生了两个bubble。

3.4 forward

3.5 Dependencies

3.5.1 Control dependencies

When an instruction is dependent on the outcome of a branch decision, these instructions are said to have a control dependence.

  • 20% of instructions are branches and jumps
  • 50% of branch and jump instructions are taken

CPI = CPI of program + % of instructions mispredicted * penalty for misprediction

控制相关其实是说,如果在分支指令中,由于跳转的目标不定,可能会导致取值错误,这样会造成流水线flush,影响流水线性能,和跳转目的相关的指令称为控制相关。(这里只是为了简单的说明问题,更精确的定义参见量化研究方法)

3.5.2 Data dependencies

When an instruction needs data from another instruction that is called a data dependence.

Type of data dependencies:

1. RAW ­ read after write. Also called Flow, True Dependence.

The following dependencies are False or Name dependencies.

2. WAW ­ write after write. Also called Output Dependence.

3. WAR ­ write after read. Also called Anti­Dependence

RAR ­read after read is not a dependence.

Dependencies and Hazards

Dependencies are caused by the program, not the pipeline.

Some dependences will not cause problems, but some, like RAW, can cause problems in pipelines. Hazards are true dependencies that result in incorrect execution of the program, but not all true dependencies will result in a hazard. Hazards are caused by both the program and the pipeline

数据相关分为真数据相关——RAW,和伪数据相关(又称名称相关)——WAW(又称输出相关),WAR(又称反相关),注意相关是程序的一种属性,和流水线无关。从名字我们可以看出,只有对于一部分真数据相关来说,才会产生流水线冒险(如果流水线不做任何处理,会导致执行结果有误)。

3.6 冒险

只有相关才会产生冒险,不同于相关这种只是程序的属性,冒险和程序,pipeline的实现这两者都有关系,一般的,冒险分为结构冒险,数据冒险,控制冒险,CPU通过不同的流水线设计手段来避免冒险,我将在后文展开。到目前为止,我们避免冒险(先保证正确再考虑性能),有三种手段了:pipeline stall, pipeline flush,forward,在现代CPU上有着更高级的技术。

四、branch prediction

我们已经知道可以通过流水线flush的方法避免控制冒险,但是这样降低了流水线的效率。我们知道分支指令跳转是不确定的,而跳转地址也不可能在IF的时候就能确定,那么如何解决这个问题呢?现代CPU解决的办法是:猜! 只要保证猜测的正确率足够高,猜测失败的惩罚在可接受范围内,那么就可以保证流水线的效率,这种技术称为branch prediction。

五、schedule

上节我们了解了流水线避免控制冒险的方法,这节主要分析避免数据冒险的方法,和上文一样可以通过stall的方法避免数据冒险,但是我们要寻求更高流水线效率,性能更高的方法。在这之前,先说明一下数据相关,我们知道,只有一部分真数据相关RAW可能产生数据冒险,其他的诸如WAR,WAW为何称为伪数据相关呢,这是由于可以通过设计pipeline完全消除这些相关,从而不会产生数据冒险,而RAW相关无法消除,可以看到,CPU设计者是如何处理这些相关性以提高性能的。

5.1 消除false dependencies

现代处理器使用一种称为register renaming的技术消除伪数据相关,我们知道程序员视图中的register称为程序寄存器(architectural register),数量一般比较少,通过引入physical register,在两种register进行映射,就可以避免false dependencies,pipeline中进行register renaming的部件称为RAT(register alias table),可以认为是一张表,保存了architectural register和physical register的对应关系:

如上图,architectural register R0~Rn,其和physical register对应关系在表中给出, R1<->P3,  R3<->P8,注意,最左表的R0-Rn标识在硬件上是没有的——反正architectural register的数量是固定的,默认按顺序排列就好了,上图只是一个逻辑示意,试图说明RAT的作用。如果在每条指令执行时,都将一个architectural register映射一个physical register,这里给一个例子:

可以看出,伪数据相关消除了——rename后绿色箭头表示的指令相关没有了,真数据相关仍然存在,对上述指令,rename后IPC提高了,即提高了指令并行度。

5.2 Tomasulo算法

本节将介绍tomasulo算法是如何最大可能减少RAW的,同时也给出该算法是如何通过register renaming消除WAW和WAR的,tomasulo的算法示意如下:

  • IQ: instruction queue
  • RF: register file
  • RS: reservation station
  • CBD:

图中没有画出load/store部件,下面的步骤也先不涉及load/store指令

tomasolu算法三个过程,对应图中高亮部分:

  • issue
  • dispatch
  • broadcast/write result (Wr)

5.2.1 ISSUE

指令的issue是顺序的

1) 从IQ中取指

2) Lookup RAT

如果RAT中对应的寄存器有值存在,使用RAT记录的值,

如果RAT中对应的寄存器没有值,使用register file中的寄存器值

3)获取空闲的RS entry

如果RS中空闲的entry,将指令放入RS中

如果RS中没有空闲entry,要等待RS空闲

4)标记(tag) 目的寄存器

将表示本条指令执行结果的寄存器存入RAT

给一个例子,是从视频中截取的,偷懒不画图了,:)

下面给出执行步骤的说明:

第一条指令是F2=F4+F1,此时RAT对应的F1,F4为空,从RF中取值F4=0.71,F1=3.14,且RS空闲,将指令放入RS后,与指令结果相关的寄存器放入RAT中,假如这里将第一条指令放在RS1中,那么最终RAT F2对应的entry填上RS1:

第二条指令F1=F2/F3,这里需要注意的是F2在RAT中对应了RS1,所以不能取RF中的值了,可以看出指令1和2是RAW,指令2需要等待指令有完成,此时RS仍有空闲,将指令放入,执行后的结果:

注意到第二条指令F1=F2/F3,第四条指令F1=F2+F3是WAW,那么有一种情况是,当issue 指令4时,指令2还没有Wr,即RS4仍然存在于RAT F1中,这时候直接将其覆盖。当指令2Wr时的动作在后面阐述。

5.2.2 dispatch

Dispatch needs to latch the results and determine which instructions are ready to execute.

dispatch指令流程是:

1)监控CBD总线,释放broadcast对应的RS

2) RS中的entry 匹配RS TAG

3)匹配成功将RS的结果插入到对应的RS entry中

4)当RS中所有操作数都准备好了,这时候可以dispatch到execution unit(adder/mulltiplier)

5) 执行单元执行完毕,将执行结果放在CBD上进行broadcast

看一个例子:

假设某个状态如上图所示,这时候dispatch锁存CBD的结果,决定去执行哪一条指令。我们看到,上图所示的cycle中锁存了RS1<->0.29这个执行结果,按照上面的步骤,先将RS1释放,这样可以后续的issue可以进来,另外,RS2,RS3,RS4中的操作数RS1都匹配了此时的结果中的RS tag(RS1),则将这三个RS entry分别替换,如下图所示:

这个时候,可以看到RS3,RS4两条指令都准备好了,由于两条指令对应不同的execution unit,那他们可以同时执行,执行完毕后,在总线上广播结果。由于总线是共享的,如果多条指令结果准备广播,该采取什么策略呢:

  • ­ Can choose the oldest instruction first ­
  • The instruction with the most dependencies goes first (how many instructions are waiting for this result)­ this is difficult to implement in hardware
  • ­ Random selection

5.2.3 Broadcast

1)将tag和result放在总线上

2)结果写入RF

3) 更新RAT,如果RAT没有对应的entry说明结果已经写入RF了

4)释放对应的RS entry——修改invalid bit

还是看一个例子:

按照上面的步骤我们得到如下结果:

broadcast stale result

我们在issue小节给出的例子有一种情况没有说明,回忆一下,指令2和指令4是WAW的,因此其在RAT entry是同一个,存在这样一种情况,当指令4issue时,指令2还没有dispatch,指令4将指令2的RAT entry覆盖了(可以去翻翻上面的图),当指令2 broadcast时,需要写入RF,但此时由于在RAT中没有entry和其对应了,它不知道写入哪一个RF,这种情况称为“stale”

这种情况该怎么办呢?这种情况下,结果不对RF和RAT进行任何更新操作,而是对所有的RS entry,检测时候匹配对应的RS Tag,如果匹配,就将对应的tag修改成result。

5.2.4 其他

遗留了几科没看:

编程基础(三)——体系结构之二相关推荐

  1. 多线程 转账_Java多线程编程基础三(原子性,可见性和有序性)

    作者简介: 华哥 10年+后端开发工作经验,主要分享:关于java体系的知识, 如:java基础知识/数据结算/算法,Spring/MyBatis/Netty源码分析,高并发/高性能/分布式/微服务架 ...

  2. 遍历二维数组_Java编程基础阶段笔记 day06 二维数组

    二维数组 笔记Notes 二维数组 二维数组声明 二维数组静态初始化与二位初始化 二维数组元素赋值与获取 二维数组遍历 二维数组内存解析 打印杨辉三角 Arrays工具类 数组中常见的异常 二维数组 ...

  3. Shell脚本编程基础 三 使用结构化命令

    结构化命令允许我们改变程序执行的顺序,在某些条件下执行一些命令而在其他条件下跳过另一些命令. (1)使用if-then语句 结构化命令中,最基本的类型就是if-then语句,其格式如下: if com ...

  4. Java编程基础阶段笔记 day06 二维数组

    二维数组 笔记Notes 二维数组 二维数组声明 二维数组静态初始化与二位初始化 二维数组元素赋值与获取 二维数组遍历 二维数组内存解析 打印杨辉三角 Arrays工具类 数组中常见的异常 二维数组 ...

  5. 原创:oracle PL/SQL编程基础 下lt;十二gt;

    游标:  游标(cursor)可以被看作指向结果集(a set of rows)中一行的指针(pointer).在oracle数据库中可以使用显示或隐式两种游标. 隐式游标: 在执行一个 sql 语句 ...

  6. Java编程基础测题(二十道)

    1.假设有如下程序: public class Demo { public static void main(String args[]) { int num = 2147483647 ; num + ...

  7. 区块链开发之Solidity编程基础(三)合约数据存储

    Solidity编程基础三 概要 以太坊虚拟机 EVM 数据位置 storage/存储 memory/内存 calldata/调用数据 Stack 栈 数据赋值成本 概要 本章将进行太坊虚拟机EVM的 ...

  8. Linux网络编程基础和一步一步学

    ·Linux网络编程 基础(一) ·Linux网络编程 基础(二) ·Linux网络编程 基础(三) ·Linux网络编程 基础(四) ·Linux网络编程 基础(五) ·Linux网络编程 基础(六 ...

  9. 操作系统内核Hack:(二)底层编程基础

    操作系统内核Hack:(二)底层编程基础 在<操作系统内核Hack:(一)实验环境搭建>中,我们看到了一个迷你操作系统引导程序.尽管只有不到二十行,然而要完全看懂还是需要不少底层软硬件知识 ...

  10. 编程之基础:数据类型(二)

    相关文章连接: 编程之基础:数据类型(一) 高屋建瓴:梳理编程约定 动力之源:代码中的"泵" 完整目录与前言 编程之基础:数据类型(二)    3.1 引用类型与值类型    41 ...

最新文章

  1. PHP实现MVC开发: 一个简单的MVC(转)
  2. 从零学React Native之12 组件的生命周期
  3. 编写书籍《C语言嵌入式系统编程修炼之道》序言
  4. python arm64_PyTorch-aarch64
  5. HDU 1232 -畅通工程(并查集)
  6. python前端学习-----Flask进阶
  7. php byte转 宽字符,C++宽字符与普通字符的转换实例详解
  8. git和gitlab安装
  9. python w3cschool_学习Python必去的8个网站
  10. java中jscrollpane_java中JScrollPane问题
  11. 百度api申请key
  12. 电脑播放SACD-ISO/DSD/DFF音乐
  13. linux核显显示独显内容,Linux驱动显示Intel第12代核显新特性:显示状态缓存
  14. python平方根_如何在Python中找到平方根?
  15. altera Cyclone V再认识
  16. 软件测试需要学习哪些技能?
  17. Tesseract怎么识别中文
  18. Qiskit 学习笔记1
  19. 电压和电流反馈判别及例子,绝对让你通透,其实也没有那么难,一次就看懂!从此终于搞懂了电压反馈和电流反馈!
  20. 三国志战略版:奸雄骑,不要奸雄

热门文章

  1. bzoj 2194: 快速傅立叶之二 FFT
  2. 解决windows下的mysql匿名登陆无法使用mysql数据库的问题
  3. HDU 3639 Hawk-and-Chicken
  4. html5-微格式-时间的格式
  5. 用eclipse调用远程webservice生成客户端代码
  6. 2015年度夏季假期学习内容
  7. 写项目文档比写代码难多了
  8. html5的优点与缺点大概总结
  9. Lucene为不同字段指定不同分词器(转)
  10. java B2B2C 多租户电子商城系统-SpringCloud动态刷新配置信息