ILP——指令级并行1:软件方法

ILP——指令级并行1

软件方法的指令级并行

循环展开
  1. 基本块的定义

    直线型代码,无分支;单入口;程序由分支语句连接基本块构成

  2. 循环级并行

    第一个思路是调整循环中的指令顺序,以减少因为相关产生的stall数

    实例如下:

    Loop: 	LD F0,0(R1) 	;F0=vector element
    		ADDD F4,F0,F2 	;add scalar from F2
    		SD 0(R1),F4 	;store result
    		SUBI R1,R1,8 	;decrement pointer 8B (DW)
    		BNEZ R1,Loop 	;branch R1!=zero
    		NOP				;delayed branch slot
    

    上述指令中可以看出如果不调整顺序,加入stall后如下

    Loop: 	LD F0,0(R1) 	;F0=vector element
    		stall
    		ADDD F4,F0,F2 	;add scalar in F2
    		stall
    		stall
    		SD 0(R1),F4 	;store result
    		SUBI R1,R1,8 	;decrement pointer 8B (DW)
    		stall ;
    		BNEZ R1,Loop 	;branch R1!=zero
    		stall 			;delayed branch slot
    

    通过调整循环内指令顺序,将没有数据相关的指令放在一起以减少stall

    Loop: 	LD F0,0(R1)
    		SUBI R1,R1,8
    		ADDD F4,F0,F2
    		stall
    		BNEZ R1,Loop 	;delayed branch
    		SD 8(R1),F4 	;altered when move past SUBI
    

    进一步优化的思想是将循环展开,每4个循环展开成一个循环,然后调整指令顺序以使得stall进一步减少

    Loop: 	LD F0,0(R1)
    		LD F6,-8(R1)
    		LD F10,-16(R1)
    		LD F14,-24(R1)
    		ADDD F4,F0,F2
    		ADDD F8,F6,F2
    		ADDD F12,F10,F2
    		ADDD F16,F14,F2
    		SD 0(R1),F4
    		SD -8(R1),F8
    		SUBI R1,R1,#32
    		SD 16(R1),F12
    		BNEZ R1,LOOP
    		SD 8(R1),F16
    
  3. 循环展开的注意事项

    • 必须保证程序运行结果不变
    • 修改指令顺序后有些指令偏移量需要修改,如跳转等
    • 不同次的循环,需要使用不同的寄存器(寄存器重命名)
    • 对于LD/SD指令,还需要确定访问的内存位置是否相关

静态指令级调度:从编译器角度看代码移动,编译器在进行代码调动时候需要注意以下几点

  1. 寄存器相关——若有相关不能并行
  2. 存储器相关——若是访问寄存器中同一块地址的相关难以直接看出
  3. 控制相关——受分支指令控制的指令不能移到分支指令之前,不受分支指令控制的指令不能移到分支指令之后

你可能感兴趣的:(#,体系结构,经验分享)