本文主要介绍TI C6000系列DSP的线性汇编格式,用法以及SIMD、循环、软件流水线、指令打包和寄存器、功能单元分配平衡等优化策略。
优化过程:
?优化根据程序剖分结果,把占用运行时间较多的模块进行优化,优化到代码能够有效的满 足需要
?三阶段:
–分析和设计C代码
–利用硬件平台信息优化C代码
–汇编优化
线性汇编与汇编不同:
不需要考虑汇编的功能单元的使用、寄存器的分配、指令是否并行以及流水线的延迟,因而不用安排软件流水;
线性汇编格式
.global__function_name
< xmlnamespace prefix ="o" />
__ function_name:.cprocfunction_parameter
.no_mdep; to indicate the complier that the memory is independent, optioned
.reguser_specified_register_name
……
.mptrregister, base+offset, stride
……
< xmlnamespace prefix ="st1" />LOOP:.tripmin_iteration_time, max_iteration_time, iteration_factor
Label:parallel bars[conditions]instructionunitoperands;comments
……
[Cntr]SUBCntr, 1, Cntr
[Cntr]BLOOP
……
.return; the value or pointer returned
.endproc
线性汇编优化考虑点
1、算法优化:
分析算法的结构,根据DSP包含的指令对算法首先进行优化,设计利于DSP结构的算法,一般这一步对于最终实现的算法的复杂度影响最大;线性汇编一般针对于运算量很大的循环体,所以合理的设计循环体的实现方法,考虑DSP的结构对已有的算法的C实现做些修正是需要的,对最终代码的性能的影响也是显著的。算法设计中可以考虑的如数据的位宽、循环前后的数据依赖关系等等。
2、数据打包处理
对于图像或者语音处理, 很多情况下的数据位宽只有8/16位,可以考虑一次加载32bit,然后使用寄存器间的并行指令(如sub4,subabs4,mpyu4,dotp4等),这样增加了数据加载处理的带宽,利用并行指令可以增大数据吞吐量。
3、减少存储区间的相关性
解决存储空间的相关性问题,即若编译器无法确定指令间或者存储器间的独立,就假设它们相互依赖,所以通过人为的对存储器的相关性进行指定,可以减少由于相关性模糊造成的存储器依赖,如C中可以用const、restrict等来指定,对于线性汇编,则采用.no_mdep伪指令来说明这个过程内的所有存储器的无关性,对于C代码则是使用-mt的编译选项说明存储器间没有重叠的。
4、减少bank冲突以及因为交叉通道造成的延迟(对于C64xx或者以上DSP)
c64系列的dsp如果同一周期访问存储器的同一个bank的数据,会造成bank冲突(每个bank都是单口存储区),具体来说若访问的地址的后2/3比特完全相同,则造成bank冲突。所以设计时可以通过.mptr来说明存储区地址间的关系,利于优化bank冲突造成的处理延迟。
交叉通道的延迟是说如果一条指令的操作数是从交叉通道传递过来的,则必须加入一个延迟cycle(数据加载指令除外),所以一个较好的方法就是对于经常使用的变量,把左右两侧各保留一个备份。
5、两侧寄存器资源的均衡
为了充分的利用A、B侧的寄存器,可以把整个循环过程分为奇数次和偶数次两部分,把奇数次迭代完全放在A侧,而偶数次迭代都放在B次,同时对于全局使用的寄存器也均分为A、B侧,这样有利于整个程序的优化,还有就是针对循环内的指令安排,应尽可能的不要过于使用只能一个功能单元完成的指令,即计算不要过多的依赖一个功能单元!还有对于乘法单元,一般其计算延迟较大,可以使用乘法单元完成其他的运算,如循环移位,字节拼接,求平均值等。
Reference:
www.dsprelated.com/groups/c6x/show/7001.php
http://houh-1984.blog.163.com/
本文主要介绍TI C6000系列DSP的线性汇编格式assembly,用法以及SIMD、循环、软件流水线、指令打包和寄存器、功能单元分配平衡等优化策略。