基于DSP的信道译碍算法优化方案
时(时钟周期)为1790。显然,性能不能达到要求,就要进入代码优化的第二阶段了。
②一般在代码调试中,最影响性能的是其中的循环代码段。而软件流水是一种用于安排循环内的指令运行方式,尽可能充分利用CPU的功能单元等资源,使循环的多次迭代能够并行执行的一种技术。在C6000的C/C++编译器里,采用软件流水使编译出来的程序代码优化是一项核心技术。所以在进一步优化之前,需要调整并尽可能简化代码的结构并去除影响软件流水的因素使其能够被编译器充分流水,这对大幅提高整个代码的性能非常重要。
所以,在考虑影响因素同时对Viterbi算法的循环代码进行如下调整;
*使用内联函数(intrinsics)替代复杂的C语言程序。C6000编译器提供了许多intrinsics,可以快速优化C代码。Intrinsics是直接参与C6000汇编指令映射的内联函数。在这里使用了 _extu(x,y,z),以简化其中hamm代码部分。
*尽管软件流水循环可包含intrinsics,但不能包含函数调用。所以需要把调用函数 hamm在循环中展开实现。
*由于编译器仅对最内部的循环执行流水,所以为了提高性能应尽可能创造一比较大的内循环。在代码中可以看到,在最内循环是i的两次循环,仅对它进行流水,对整个代码的性能提高不大。所以一个想法是,将i和j循环全部展开,使编译器直接面对最大的C循环以最大发挥软件流水的作用。
*另外,展开循环后代码中的变量如果可以确定其运行中的值,就尽量以实值代入,这样减少了变量个数,也就是减少了所需分配的寄存器个数(C62xxCPU中有32个寄存器)。
在进行上述调整后运行代码,进行测试发展,性能没有太大改善;用编译器反馈表(feedback)进行观察发现,循环并没有发生流水。这是为什么呢?原来在展开内部循环后导致C循环内代码尺寸太大,需要的寄存器数目大于C62XX 的32个寄存器,所以不能进行软件流水。为了解决这问题,需要简化循环或将循环拆成几个小循环。在这里先将C循环内部的小循环展开,然后将其拆成分别完成度量计算和累计度量比较的两个循环,这样就减小了每个循环中的代码尺寸。限于篇幅这里只写出累计度量比较的循环代码。
/*完成累计度量比较的循环*/
accum00=accum_err_metric[0];accum10=accum_err_metric[1];
accum20=accum_err_metric[2];accum30=accum_err_metric[3];
for(c=0;c<n;c++)//n=24
{sh_ptr++;
add1=accum10+branch_metric_array[c][1];
add2=accum00+branch_metric_array[c][0];
add3=accum10+branch_metric_array[c][0];
add4=accum00+branch_metric_arrcy[c][1];
add5=accum30+branch_metric_array[c][2];
add6=accum20+branch_metric_array[c][3];
add7=accum30+branch_metric_array[c][3];
add8=accum20+branch_metric_array[c][2];
if(add1>add2){accum00=add2;state_history[0][sh_ptr]=0;}
else{accum00=add1;state_history[0][sh_ptr]=1;}
if(add3>add4){accum20=add4;state_history[2][sh_ptr]=0;}
else{accum20=add3;state_history[2][sh_ptr]=1;}
if(add5>add6){accum30=add6;state_history[3][sh_ptr]=2;}
else{accum30=add5;state_history[3][sh_ptr]=3;}
if(add7>add8){accum10=add8;state_history[1][sh_ptr]=2;}
else{accum10=add7;state_history[1][sh_ptr]=3;}
}
accum_err_metric[0]=accum00;accum_err_metic[1]=accum10;
accum_err_metric[2]=accum20;accum_err_metric[3]=accum30;
其中accum_err_metric为状态i的累计度量值,branch_metric_array[][]为计算得到的各时刻量值,原来代码中的二维数码mextstate[j]被以实值代入。另外在编程考虑时要注意一点:程序中对数据的取命令(load)是非常耗时的,所以应考虑尽量减少对数据数组的操作。在上面程序的改进中,先从数组中取出要进行循环处理的累计度量值,再使用accumXX及addX作为各次迭代的中间变量,在循环后将最后的结果放入数据。这样就大大减少了对数组的操作,从而使优化进一步提高。
*编译器优化选项的选择。C6000 C/C++编译器提供了大量的编译选项,供用户在编译时选择使用。这些选项中的部分会直接影响或控制编译器优化过程,因而会影响编译输出的代码优化性能。选择适合的选项,能极大地提高优化性能。在这里使用的优化选项有:
-03--表示可得到最高程度的优化,编译器将执行各种优化循环的方法,如软件流水、循环展开等等。
-pm--在使用-o3选项进行优化时尽量联合使用-pm选项,-pm是程序级优化,使优化器访问整个程序,了解循环次数。
-op1--使用了外部变量,但未使用外部函数调用。
-g--使能符号调试和汇编源语句调试。
DSP Viterbi算法 通信信道 C6000 相关文章:
- 在采用FPGA设计DSP系统中仿真的重要性 (06-21)
- 基于 DSP Builder的FIR滤波器的设计与实现(06-21)
- 达芬奇数字媒体片上系统的架构和Linux启动过程(06-02)
- FPGA的DSP性能揭秘(06-16)
- 用CPLD实现DSP与PLX9054之间的连接(07-23)
- DSP+FPGA结构在雷达模拟系统中的应用(01-02)