指令级并行
Posted yizui
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了指令级并行相关的知识,希望对你有一定的参考价值。
基于《计算机体系结构:量化研究方法》第3章 指令级并行及其开发
本章内容主要面向计算机设计人员和编译器开发者,因此只记录一些感兴趣的点。
介绍
指令级并行(ILP)就是多条指令同时执行,达到提升性能的目的。因为执行一条指令可以分为多个操作(取码、译码、执行等),所以可以通过流水线模式做到ILP。
每个操作都是独立的功能单元来处理
指令相关性
指令之间可能存在相关性,即后面的指令需要等待前面的指令完成,这会导致流水线停顿。
有以下几种相关
- 数据相关:当前指令的输出数据是后面指令的输入数据
- 名称相关:数据无关的指令使用了相同的寄存器或存储器地址。通过寄存器重命名可以规避名称相关
- 控制相关:分支块里的指令依赖于分支控制指令的结果
乱序执行
当出现相关指令时,可以通过重排序,将无关的指令提前执行(乱序执行),避免流水线停顿。
重排序可以是
- 硬件层的乱序执行单元
- 编译器在编译时调整指令顺序,有必要时可以展开循环增加指令,更便于得到充分并行的指令。
重排序需要注意规避以下三种数据风险
- RAW(写后读):指令j试图在指令i写入一个位置之前读取数据,此时指令j读取到旧值
- WAW(写后写):指令j试图在指令i写入一个位置之前写入数据,此时最终数据为指令i写入的数据。
- WAR(读后写):指令j试图在指令i读取一个位置之前写入数据,此时指令i读取到错误的新值。
此外如果是控制相关的话,重排序还需要遵循以下两个约束
- 如果指令与分支控制相关,则不能移动到分支控制前,使该指令脱离分支控制
- 如果指令与分支控制无关,则不能移动到分支控制后,使该指令受分支控制
精确异常
当指令执行出现异常时,需要回退该指令之后的指令执行结果。乱序执行时,后续指令的结果可能已经写入寄存器或存储器,回退成本很高,因此就有了重排序缓存。乱序执行的指令执行结束后会先保存在重排序缓存中,最后顺序提交。当出现异常时,不提交即可,做到精确异常。
分支预测
当存在控制相关的指令时,如果发生跳转,那么流水线中的后续指令可能都会失效,这会导致严重的性能损耗。为了解决这问题,就有了分支预测。
结语
很多优化其实都是由编译器完成的,对于像我这种级别的程序员来说,就是知道
- 要使用内存栅栏,保证程序结果不受乱序执行的影响。
- 可以使用GNU扩展的
__builtin_expect()
函数来增加分支预测的准确率。
以上是关于指令级并行的主要内容,如果未能解决你的问题,请参考以下文章