软件流水循环
1. C6000流水线(Pipeline)
一个指令的处理过程并不是一步完成,它被分为三个阶段:取指(Fetch)、译码(Decode)、执行(Excute)。将每一个阶段放入独立的流程车间处理,形成流水线式的处理过程,可以大大加快指令的处理速度。
如图1所示,流水编排后的3个指令只需5个cycle,相比顺序执行的9个cycle大大减少,当指令数增多,流水线的优势将更加明显。
图1 简单的流水线编排示意
实际上,C6000架构把每一个阶段进一步划分为多个子阶段,每个子阶段消耗1个CPU cycle。
取指(4个子阶段):
PG: Program address generate (update program counter register)
PS: Program address send (to memory)
PW: Program (memory) access ready wait
PR: Program fetch packet receive (fetch packet = eight 32-bit instructions)
译码(2个子阶段):
DP: Instruction dispatch (or assign, to the functional units)
DC: Instruction decode
执行(1-10个子阶段,指令间有区别):
E1 – E10, where E1 is the first sub stage in the execute stage
图2 高性能的C6000流水线
2. 流水线阻塞
下列两种情况出现时,流水线将被阻塞:
当前为load、complex multiply等具有多个延时时隙(delay slot)的指令时,下一指令需多个cycle,等其返回结果后才能往下继续执行
跳转指令出现时,CPU无法预知下一步执行哪个分支指令,因此跳转目标指令需等到跳转指令执行到E1阶段才能进入流水线
为了充分利用流水线的资源,避免delay slots造成的阻塞,C6000架构在软件和硬件上分别新增了一个处理机制:
软件上:提供软件流水(software pipelining)指令编排
硬件上:提供SPLOOP buffer(software pipelining loop buffer)
3. 软件流水
软件流水≠流水线!
软件流水技术指编译器通过重新调整指令的位置,使得原本将发生阻塞的流水线得以充分利用,其重点在“软件”两字。
例如处理下面循环:
for(i=0; i<15; i++)
{
sum += tab;
}
传统指令流程(Solution1)和软件流水编排后的指令流程(Solution2)如图3所示:
图3 传统编排 Vs 软件流水编排
从图中看到,经过软件重新编排过的指令将不再发生流水线阻塞,提升运行效率的同时也不影响代码功能的实现。
解释下有关软件流水的三个名词:
流水核(Kernel):流水线被充分利用的一段代码
流水填充(Prolog):流水核之前的一段填充过程代码
流水排空(Epilog):流水核之后的一段排空过程代码
4. SPLOOP Buffer
软件流水将会带来两个主要的缺点:汇编文件代码尺寸的增加并影响代码的中断属性。
SPLOOP Buffer的出现就是为了就解决以上问题。SPLOOP Buffer是C6000内部的一个存储区域,用来装载SPLOOP指令。当一个SPLOOP 第一次被执行时,循环的相关指令被拷贝到SPLOOP Buffer中,整个循环运行过程将从这里取指执行,直到循环结束。
C6000还为SPLOOP Buffer的使用提供了专门的寄存器和操作指令,如果编程者使用汇编/线性汇编编程,需要熟悉这些指令和寄存器,并了解SPLOOP Buffer特有的执行机制(参考文献[1]),如果使用C/C++编程则由编译器自动生成相应指令。
以存储块拷贝函数为例,示意使用SPLOOP Buffer前后的编码效果:
图4 memery copy 使用SPLOOP buffer前
图5 memery copy 使用SPLOOP buffer后
*注意:SPLOOP Buffer最多只能存放14个执行包(每个执行包可含8条指令,顺序/并行),因此如果循环体较复杂将不能使用SPLOOP Buffer。
5. 导致软件流水编排失败的因素
在CCS开发环境中,开启-O2/-O3优化选项,编译器将自动为合适的代码进行软件流水编排,因此编程者需要注意的是使设计的循环体符合软件流水编排的条件。
下列一些因素将可能引起软件流水编排失败:
汇编语句嵌入到C/C++代码中
出现复杂的流控制语句如goto、break等
循环中包含一个调用(内嵌函数除外)
需进行软件流水编排的指令太多
没有初始化循环计数器
循环变量在循环过程中被修改
软件流水被关闭:没有使用-O2或-O3选项;使用了-ms2或-ms3选项;使用-mu关闭了软件流水
很好的分享。