超长指令字
引用声明
本文大量图片及内容来自以下网站及作品
- An Introduction To Very-Long Instruction Word (VLIW) Computer Architecture(Philips Semiconductors)
- https://en.wikipedia.org/wiki/Very_long_instruction_word
- ECE 4750 Computer Architecture :Topic 13: VLIW Processors(Christopher Batten School of Electrical and Computer Engineering Cornell University )
超长指令字定义
超长指令字(VLIW:Very long instruction word)指的是一种被设计为可以利用指令级并行(ILP)优势的CPU体系结构。传统的中央处理单元(CPU,处理器)通常只允许程序指定仅顺序执行的指令,而VLIW处理器允许程序明确指定并行执行的指令。此设计旨在能避开一些其他设计固有的缺点,实现更高的性能。
改善处理器性能的传统方法包括将指令分为多个子步骤,以便可以部分同时执行这些指令(称为流水线),在处理器的不同部分(超标量体系结构)甚至独立调度要独立执行的指令,甚至以不同于程序的顺序执行指令(乱序执行)。这些方法都使硬件复杂化(电路更大,成本和能耗更高),因为处理器必须在内部做出所有决策才能使这些方法起作用。(如超标量,流水线技术)
相反,VLIW方法取决于程序,程序会决定同时执行哪些指令以及如何解决冲突。实际上,这意味着编译器(用于创建最终程序的软件)变得更加复杂,但是硬件比许多其他并行方式更简单。
VLIW的特点
对比cisc和risc,我们可以看出VLIW的特点有:定长指令,一条指令为简单功能的聚合,许多通用寄存器,是加载/存储结构,硬件设计逻辑偏向多管道,无微代码,调度简单.
相比cisc,vliw更像是几个risc的结合,与risc有着更为相似的特点.
对于下图同样一段c语言代码,cisc,risc,vliw的编译结果如下所示
从上图的对比来看,VLIW看起来还是相当的低效的,但当我们有一个更加强大的编译器时,每一条VLIW的指令槽都会被尽可能的填满,当有优化的时候,risc和vliw的指令就可能会是下面的样子
从另一个观点来看,cisc指令的设计原则在于取出指令,执行完毕后在进行下一条,所以其本质上是线性的.而risc在设计时就已经考虑到管道技术的便利性,形象的讲,取出指令,放进管道,就直接去下一条指令了.但无论是哪一种,本质上他们都是单发射的.
vliw则是从根本上明确了他的并行性,即单指令是多个功能的聚合,与上面两者依靠硬件来完成并行不同,vliw通过编译来实现并行.这依赖于编译器对指令集的可见度比硬件要大很多,而且编译器可以对源代码进行各项分析优化,最后,大量的寄存器可以轻易实现超标量的重排缓冲的功能.
超长指令字原理
VLlW处理器的一个超长指令字包含多个操作字段,每个字段可与相应的功能部件对应。这些操作字段包括可并行执行的多个运算器控制指令字段、若干个存储器控制指令字段和其他操作控制字段。
各运算部件和共享的大容量寄存器堆直接相连,以便提供运算所需要的操作数或存放运算结果,对数据的读/写操作也可以通过存储器指令字段对指定存储模块中的存储单元进行。运行时不需要用软件或硬件来检测其并行性,而直接由超长指令字来控制机器中多个相互独立的功能部件并行操作。虽然这种字段控制方式的思路来自于微程序控制器的水平微指令方式,但微指令只对一个运算部件进行控制,而VLIW是对多个功能部件并行控制。
实际上,VLIW的实现是由编译器将多条可以发送的标准指令捆绑在一条超长指令字中。基于多个可以同时执行的功能部件的支持,处理器在一个时钟周期内可以发射超长指令字中的多条指令,实现多条指令的并行执行。
由于VLlW指令中的字段数是固定的,因此要提高VLIW处理器同时发射指令的条数,就需要重新设计VLlW指令格式,增加有关功能部件,并重新设计编译系统。这与同样具有多发射指令的超标量处理器不同。超标量处理器具有多条指令执行流水线,指令的并行性由处理模块硬件来检验,无须编译保证。增加处理模块的个数有可能提高超标量处理器同时发射指令的条数。
超长指令字指令格式
每个VLIW的指令可能包括两个整数操作、两个浮点操作、两个访存操作和一个分支操作。如下图所示(下图没有分支指令)
每条指令对应于每个功能单元有几个域,每个功能单元可能占用16到24位,从而指令长度达到112到168位。为了充分利用功能单元,要求代码序列必须有较大的并行度来有效填充操作槽。通过循环展开和使用全局的调度技术来对基本块进行调度可获得较高的并行度。除了通过循环展开消除分支转移的开销,全局调度策略可将指令跨转移点移动。
超长指令字也有助于开发程序中的指令级并行性。一个超长指令字包含了多条基本指令(primitive instructions),它们被发送到不同的VLIW入口中并行执行。但是这个能力不是在执行时由硬件负责,而是由编译器赋予的。编译器在生成的目标代码中把彼此独立的基本指令分到一个组里,以并行执行。由于超长指令字处理器不需要动态调度,也不需要进行重定向操作,所以它的控制逻辑相当简单。
相关技术
超长指令字通常会利用两个技术,循环展开和软件管道.
对于上图中的c语言循环,我们将其翻译为mips汇编代码为左下.
其中每一个周期执行1/8=0.125条浮点指令
DADDI:把一个寄存器的内容加上一个立即数:DADDI R1,R2,#3
DADDIU:把一个寄存器的内容加上一个无符号的立即数:DADDIU R1,R2,#3
LW:从存储器中读取一个字的数据到寄存器中:LW R1, 0(R2)
我们对内层循环进行展开,让其一次进行四个迭代(不能整除4的部分单独处理)
再进行汇编,一个周期执行0.36条add.s指令
加上软件管道技术,1个周期执行1条adds指令
我们可以看到,在加入了软件管道技术以后,效率有了大量的提升.我们可以看到,软件管道只在开启与关闭的时候会有额外的开销.
追踪调度也是一项常用的技术
优化流图中最经常执行的代码路径(可以牺牲很少执行代码路径的执行之间)
步骤:画出数据流图找到最常执行路径——优化路径——补偿(比如跳过了某些分支的相应处理)
优点:找到没有数据依赖的最常执行路径,提高运行效率
缺点:需要profile,增加编译时间;补偿代码容易导致代码膨胀;目标代码必须存在主要路径才有好的效果。
"经典"vliw缺点
- 需要对每一台机器重新编译,即使是同一型号的两台不同机器
- 目标代码体积大
- 指令填充占据位置大,展开和管道技术重复代码多
- 无法通过静态编译解决的分支问题
- VLIW难以处理内存操作,因为无法确定指令执行时延
- 需要确定branch的预测结果