21ic电子技术开发论坛

标题: DSP程序优化 [打印本页]

作者: dingy    时间: 2012-10-10 19:39
标题: DSP程序优化
谁有一些方法呢?
作者: dingy    时间: 2012-10-10 19:39
我先分享一个使用并行代码

尽可能把长的有依赖的代码链分解成几个可以在流水线执行单元中并行执行的没有依赖的代码链。很多高级语言,包括 C++ ,并不对产生的浮点表达式重新排序,因为那是一个相当复杂的过程。需要注意的是,重排序的代码和原来的代码在代码上一致并不等价于计算结果一致,因为浮点操作缺乏精确度。在一些情况下,这些优化可能导致意料之外的结果。幸运的是,在大部分情况下,最后结果可能只有最不重要的位(即最低位)是错误的。

不好的代码:

double a[100] , sum ;

int i ;

sum = 0.0f ;

for (i=0 ; i<100 ; i++)

sum += a ;



推荐的代码:

double a[100] , sum1 , sum2 , sum3 , sum4 , sum ;

int i ;

sum1 = sum2 = sum3 = sum4 = 0.0 ;

for (i = 0 ; i < 100 ; i += 4)

{

   sum1 += a ;

   sum2 += a[i+1] ;

   sum3 += a[i+2] ;

   sum4 += a[i+3] ;

}

sum = (sum4+sum3)+(sum1+sum2) ;
作者: houcs    时间: 2012-10-10 20:08
对,要注意的是: 使用 4 路分解是因为这样使用了 4 段流水线浮点加法,浮点加法的每一个段占用一个时钟周期,保证了最大的资源利用率。
作者: ousj    时间: 2012-10-10 20:09
避免没有必要的读写依赖

当数据保存到内存时存在读写依赖,即数据必须在正确写入后才能再次读取。虽然 AMD Athlon 等 CPU 有加速读写依赖延迟的硬件,允许在要保存的数据被写入内存前读取出来,但是,如果避免了读写依赖并把数据保存在内部寄存器中,速度会更快。在一段很长的又互相依赖的代码链中,避免读写依赖显得尤其重要。如果读写依赖发生在操作数组时,许多编译器不能自动优化代码以避免读写依赖。所以推荐程序员手动去消除读写依赖,举例来说,引进一个可以保存在寄存器中的临时变量。这样可以有很大的性能提升。
作者: dousfoulexd    时间: 2012-10-10 20:11
看看
作者: liuzaiy    时间: 2012-10-10 20:11
能举个例子吗?
作者: yinxiangh    时间: 2012-10-10 20:11
不好的代码:

float x[VECLEN] , y[VECLEN] , z[VECLEN] ;

。。。。。。

for ( unsigned int k = 1 ; k < VECLEN ; k ++)

{

   x[k] = x[k-1] + y[k] ;

}

for (k = 1 ; k <VECLEN ; k++)

{

   x[k] = z[k] * (y[k] - x[k-1]) ;

}

推荐的代码:

float x[VECLEN] , y[VECLEN] , z[VECLEN] ;

。。。。。。

float t(x[0]) ;

for ( unsigned int k = 1 ; k < VECLEN ; k ++)

{

   t = t + y[k] ;

   x[k] = t ;

}

t = x[0] ;

for (k = 1 ; k < ; VECLEN ; k ++)

{

   t = z[k] * (y[k] - t) ;

   x[k] = t ;

}
作者: morrisk    时间: 2012-10-10 20:13
循环不变计算

对于一些不需要循环变量参加运算的计算任务可以把它们放到循环外面,现在许多编译器还是能自己干这件事,不过对于中间使用了变量的算式它们就不敢动了,所以很多情况下你还得自己干。
作者: morrisk    时间: 2012-10-10 20:14
对于那些在循环中调用的函数,凡是没必要执行多次的操作通通提出来,放到一个 init 函数里,循环前调用。
作者: 栩栩如生    时间: 2012-10-10 20:17
对,另外尽量减少喂食次数,没必要的话尽量不给它传参
作者: 栩栩如生    时间: 2012-10-10 20:17
需要循环变量的话让它自己建立一个静态循环变量自己累加,速度会快一点。
作者: zyf部长    时间: 2012-10-10 20:23
还有就是结构体访问,东楼的经验,凡是在循环里对一个结构体的两个以上的元素执行了访问,就有必要建立中间变量了
作者: zyf部长    时间: 2012-10-10 20:23
结构这样,那 C++ 的对象呢 ? 想想看
作者: llljh    时间: 2012-10-10 20:26
有例子说明吗?
作者: ousj    时间: 2012-10-10 20:27
旧代码 :

total =

a->b->c[4]->aardvark +

a->b->c[4]->baboon +

a->b->c[4]->cheetah +

a->b->c[4]->dog;

新代码 :

struct animals * temp = a->b->c[4];

total =

temp->aardvark +

temp->baboon +

temp->cheetah +

temp->dog;

一些老的 C 语言编译器不做 聚合优化 ,而符合 ANSI 规范的新的编译器可以自动完成这个优化,看例子 :

float a , b , c , d , f , g;

。。。

a = b / c * d;

f = b * g / c;

这种写法当然要得,但是没有优化

float a , b , c , d , f , g;

。。。

a = b / c * d;

f = b / c * g;

如果这么写的话,一个符合 ANSI 规范的新的编译器可以只计算 b/c 一次,然后将结果代入第二个式子,节约了一次除法运算。
作者: 司徒老鹰    时间: 2012-10-10 20:29
学习了
作者: dingy    时间: 2012-10-10 20:31
内容真是丰富,多谢大家了
作者: yanzi0700    时间: 2012-10-10 21:03
学习了!
作者: 好吧你赢了    时间: 2012-10-11 16:25
学习了




欢迎光临 21ic电子技术开发论坛 (https://bbs.21ic.com/) Powered by Discuz! X3.5