C-LEVEL 优化

1,使用-INLINE

当你的代码中的函数已经是使用开发者定制的最优化代码,无需编译器自行优化修改时使用这个关键字。或者是一些开关,用法如下:
Usage: -INLINE:
Switches:
={on|off}
none
all
must=routine_name[,routine_name]*
never=routine_name[,routine_name]*
Static={on|off}

例如:

INLINE:never=foo:must=barINLINE:static=on

2,尽量减少函数的形参

函数的形参太多的时候就要做成结构体,例如:

Instead of:
void init_func(int n,
short lim,
int x,
int y,
int z,
short *p1,
short *p2,
int *p3,
int *p4,
int *p5);

Use:

typedef struct { 
int n; 
short lim;
 int x;
 int y; 
int z;
 short *p1; 
short *p2;
 int *p3;
 int *p4; 
int *p5;
 } params_t; 
void init_func(params_t *args);

3,合理的优化等级

降低cycle数的最优组合: –O4 –Os0
降低代码量的最优组合: –O3 –Os4
在关键代码处(内核)使用-O4来得到最佳性能
在非关键处使用-O3 -Os[1-4] 来得到最佳综合性能

4,降低取地址,static,和全局变量的使用频率

编译器不会为这三种变量分配寄存器,所以它们的运算速度很慢,要将少它们的使用次数。例如:
Instead of:

int global_counter;
void func(int *p)
{
int i;
for (i=0; i
{
foo();
global_counter++;
}
}

Use:

int global_counter;
void func(int *p)
{
int i;
int local_counter=0;
for (i=0; i
{
foo(); // foo() doesn’t access global_counter
local_counter++;
}
global_counter += local_counter;
}

5,将循环体中的内容降到最小

6,循环体的循环次数设置为已知

Instead of:

for (i=0; i<foo();i++)
{
...
}

Use:

int limit = foo();
for (i=0; i<limit;i++)
{
…
}

Instead of:

while ((*p != 0) && (i<200))
 { 
…
 i++; 
}

Use:

while ( i<200 ) 
{
 if (*p == 0) 
break;
 …
 i++;
 }

7,使用intrinsics和库函数

例如

memcpy( x, y, LIMIT*sizeof( int ) ); 
memset( arr, 0, LIMIT*sizeof( int ) );

而不要手动取循环赋值

8,控制循环体的展开

  • #pragma dsp_ceva_unroll= 告诉编译器循环展开N次
    #pragma dsp_ceva_trip_count = 告诉编译器估计的行程为N
    #pragma dsp_ceva_trip_count_factor = 告诉编译器迭代次数可以被N除尽
    #pragma dsp_ceva_trip_count_min = 告诉编译器迭代次数最少为N次
    -OPT:unroll_times_max=1 告诉编译器,全局的循环展开次数最大为1
    #pragma dsp_ceva_unroll=1 告诉编译器,某个局部的循环展开次数最大为1

例1:

void foo(int* in, int* out, int N) {
int i = 0;
for(i=0; i
#pragma dsp_ceva_unroll=1
{
*out = *in++;
out++;
}
}

生成的汇编为:

; Guarding if may be created in 
; cases where software pipeline 
; optimization occurs; Loop Body 
PCU.bkrep {ds1} lci0.ui 
SC0.nop 
{
LS0.ld (r3.ui).i +#4, modu0.i
LS0.st modu0.ui, (r4.ui).i+#4
}

例2:

void foo(int* in, int* out, int N)
 {
 int i = 0; 
for(i=0; i<N;i++)
#pragma dsp_ceva_unroll=2 
{
 *out = *in++; 
out++;
 } 
}

生成的汇编为:

; Guarding if may be created in 
; cases where software pipeline 
; optimization occurs
 … 
 SC0.cmp {le} modu0.i, #0, pr0
 || SC1.mov r0.i, r4.i
 || SC2.mov r1.i, r3.i
 || SC3.shiftr r5.i, #0x1, r1.i
 SC0.nop
 PCU.brr {t} #BB18_foo ,?pr0
BB11_foo:; Reminder loop
 LS0.ld (r4.ui).i +#4, modu0.i
 || SC0.shiftr r5.i, #0x1, r1.i
 LS0.st modu0.ui, (r3.ui).i+#4; Loop Body
 PCU.bkrep lci0.ui
 {
 LS0.ld (r4.ui).i +#4, modu1.i
 LS0.st modu1.ui, (r3.ui).i+#4
 LS0.ld (r4.ui).i +#4, modu0.i
 LS0.st modu0.ui, (r3.ui).i+#4
 }

例3:

void foo(int* in, int* out, int N)
 {
 int i = 0; 
for(i=0; i<N;i++)
#pragma dsp_ceva_unroll=2 
#pragma dsp_ceva_trip_count_min=2
{
 *out = *in++; 
out++;
 } 
}

生成的汇编为:

; Guarding if will not be created in this case 
 … 
 SC0.cmp {le} modu0.i, #0, pr0
 || SC1.mov r0.i, r4.i
 || SC2.mov r1.i, r3.i
 || SC3.shiftr r5.i, #0x1, r1.i
 SC0.nop
 PCU.brr {t} #BB18_foo ,?pr0
BB11_foo:; Reminder loop
 LS0.ld (r4.ui).i +#4, modu0.i
 || SC0.shiftr r5.i, #0x1, r1.i
 LS0.st modu0.ui, (r3.ui).i+#4; Loop Body
 PCU.bkrep lci0.ui
 {
 LS0.ld (r4.ui).i +#4, modu1.i
 LS0.st modu1.ui, (r3.ui).i+#4
 LS0.ld (r4.ui).i +#4, modu0.i
 LS0.st modu0.ui, (r3.ui).i+#4
 }

例4:

void foo(int* in, int* out, int N)
 {
 int i = 0; 
for(i=0; i<N;i++)
#pragma dsp_ceva_unroll=2 
#pragma dsp_ceva_trip_count_min=2
#pragma dsp_ceva_trip_count_factor=2
{
 *out = *in++; 
out++;
 } 
}

生成的汇编为:

 ; Loop Body
 PCU.bkrep lci0.ui
 {
 LS0.ld (r4.ui).i +#4, modu1.i
 LS0.st modu1.ui, (r3.ui).i+#4
 LS0.ld (r4.ui).i +#4, modu0.i
 LS0.st modu0.ui, (r3.ui).i+#4
 }

9,告诉编译器指针内容不能混叠

使用以下指令:
1)-OPT:alias=restrict
所有指针指向的内存不重叠,严格独立
2)-OPT:alias=strongly_typed
指针中不同类型的数据指向不同的独立内存
3)使用 restrict关键字修饰形参
例如:

void vec_mem_copy( int *__restrict__ p1, int *__restrict__ p2, int n) 
{ 
… 
OR -OPT:alias=restrict

生成的汇编为:
不告诉编译器内存不混叠:

; 5 cycles per iteration
PCU.bkrep lci0.ui
{
LS0.ld (r4.ui).i +#4, modu3.i
SC0.nop
SC0.nop
SC0.add modu3.i, #80, modu3.i
LS0.st modu3.ui, (r3.ui).i+#; Additional unrolled iterations
}

告诉编译器内存不混叠:

; 1 cycle per iteration
PCU.bkrep lci0.ui
 { 
 LS0.st r2.ui, (r3.ui).i+#4
 || LS1.ld (r4.ui).i +#4, r2.i
 || SC0.add r0.i, #80, modu2.i; Additional unrolled iterations
 }

大大降低了cycle数!!

10,局部变量能使用32bit就不要用16bit

例如:

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

要比

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

cycle数更少

11,”宽拷贝机制”,宽bit赋值

12,减少if-esle的条件

例如:

if (y > 0)
{
x = 1;
}
else
{
x=0;
}

可改为:

x=0; 
if (y > 0) 
{
 x = 1;
 }

附:
注意,OPT表示全局设置,#pragma设置局部

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值