赞
踩
指令调度:找出不相关的指令序列,让它们在流水线上重叠并行执行。
制约编译器指令调度的因素
为了讨论方便,以下内容使用的浮点流水线的延迟如下表
产生结果的指令 | 使用结果的指令 | 延迟(cycles) |
---|---|---|
浮点计算 | 另一个浮点计算 | 3 |
浮点计算 | 浮点store(S.D) | 2 |
浮点Load(L.D) | 浮点计算 | 1 |
浮点Load(L.D) | 浮点store(S.D) | 0 |
再假设:分支延迟,整数load延迟都是1,整数运算部件每个时钟都能流出一条整数指令。
例6.1 对于下面的源代码,转换成MIPS汇编语言,在不进行指令调度和进行指令调度两种情况下,分析其代码一次循环所需的执行时间。
for (i=1000; i>0; i--) x[i] = x[i] + s;
- 1
- 2
解:
先把该程序翻译成MIPS汇编语言代码
Loop: L.D F0, 0(R1)
ADD.D F4, F0, F2
S.D F4, 0(R1)
DADDIU R1, R1, #-8
BNE R1, R2, Loop
在不进行指令调度
的情况下,根据表中给出的浮点流水线中指令执行的延迟,程序的实际执行情况如下:
指令流出时钟 | |
---|---|
Loop: L.D F0, 0(R1) | 1 |
(空转) | 2 |
ADD.D F4, F0, F2 | 3 |
(空转) | 4 |
(空转) | 5 |
S.D F4, 0(R1) | 6 |
DADDIU R1, R1, #-8 | 7 |
(空转) | 8 |
BNE R1, R2, Loop | 9 |
(空转) | 10 |
可以看出,每完成一个元素的操作需要10个时钟周期,其中有五个是空转周期。
在用编译器对上述程序进行指令调度
以后,程序的执行情况如下:
指令流出时钟 | |
---|---|
Loop: L.D F0, 0(R1) | 1 |
DADDIU R1, R1, #-8 | 2 |
ADD.D F4, F0, F2 | 3 |
(空转) | 4 |
BNE R1, R2, Loop | 5 |
S.D F4, 0(R1) | 6 |
进一步分析:
有效操作
的比率?循环展开
开发循环级并行
的有效方法例6.2 将例6.1中的循环展开3次得到4个循环体,然后对展开后的指令序列在不调度和调度两种情况下,分析代码的性能。假定R1的初值为32的倍数,即循环次数为4的倍数。消除冗余的指令,并且不要重复使用寄存器。
展开后没有调度的代码
如下(需要分配寄存器)
50%是空转周期
,程序执行效率极差调度后
的代码如下(没有空转周期!):
结论:
循环展开和指令调度的注意事项
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。