指令调度是为了提高指令级并行(ILP),对于超长指令字(VLIW, Very Long Instruction Word)和多发射系统,ILP是可以有效提高硬件利用率。
指令调度的约束
指令调度也是一种程序的优化pass,需要遵循以下约束:
- 数据依赖约束。调度后代码执行结果需要和调度前相同。
- 控制依赖约束。所有调度前程序执行的指令都必须在调度后的程序中执行。
- 资源约束。调度不能超过机器上的资源。
数据依赖包括真依赖、反依赖、输出依赖和输入依赖,相关概念可以参阅 数据依赖和控制依赖 Data Dependence and Contol Dependence。前3种依赖约束了指令的执行顺序,但其中只有真依赖的依赖关系是不可解除的,而反依赖和输出依赖都可以通过使用不同的变量来解除依赖关系。
一个基本块(BB)内指令只要满足数据依赖就可以进行任意重新排序,但基本块内的程序通常都很少,重排提升并行性非常有限。提高基本块之间的并行性就至关重要了。基本块间指令的调度需要遵循控制依赖的约束,如果指令a的结果决定了指令b是否执行,则称指令b控制依赖于指令a。控制依赖相关概念可以参阅 数据依赖和控制依赖 Data Dependence and Contol Dependence。
资源约束是显而易见的,调度肯定不能超过机器物理资源的限制。
基本机器模型
在介绍指令调度前,先假设下我们的基本机器模型:
对于一个基本数学运算:
- 需要一个ALU单元的物理资源
- 需要一个时钟(clock)的时间
对于Loads (LD) 和 Stores (ST):
- 需要一个MEM(Memory buffer)单元的物理资源
- ST需要一个时钟时间。LD需要两个时钟时间才能完成,但是我们可以在下一个时钟ST到相同的内存位置,并且每个LD可以在任意时钟发射。
基本块调度
先从最简单的基本块调度说起,这里介绍列表调度(list scheduling)的方法。基本块内的指令顺序其实就是一种拓扑排序,基本块调度的目的是找到一种性能最佳(并行度最高)的拓扑排序。
一个基本块内的指令构建一个数据依赖图(data-dependece graph):
- 节点就是基本块内的每条指令
- 边代表两条指令间的数据依赖, i → j i\rightarrow j i→

946

被折叠的 条评论
为什么被折叠?



