代码优化方法
1.Loop Unrolling解开循环
说明:
适用于短循环,以此来避免循环的overhead
可以减少分支带来的性能损耗
应该在代码大小和性能之间做出一定的平衡
例子:
for ( i=0; i < 3; i++) {
z[i] = a[i] + b[i];
}
——————————————–
z[0] = a[0] + b[0];
z[1] = a[1] + b[1];
z[2] = a[2] + b[2];
——————————————–
2. Code motion移动代码
说明:将循环内的不必要的代码移出循环外。
例子:
for ( i=0; I < N*M; i++) {
z[i] = a[i] + b[i];
} // N*M is by default within the loop
——————————————–
temp = N*M;
for ( i=0; I < temp; i++) {
z[i] = a[i] + b[i];
} // N*M is explicitly put outside the loop
——————————————–
3. Induction variable 递增(or 归纳)变量?
for (i=0; i<N; i++)
for (j=0; j<M; j++)
z[i][j] = b[i][j];
不如在每个循环中计算i*M+j ,在数组中共享递增(or 归纳)变量,每个循环末尾加1
zbinduct = 0;
for (i=0; i<N; i++)
for (j=0; j<M; j++){
*(zptr + zbinduct) = *(bptr + zbinduct) ;
zbinduct ++ ;
}
}
4.Strength reduction强度降低?
用位操作代替乘除
例子:
unsigned int x;
Y = 2*x;
————–
// same result as
Y = x << 2;
5. Memory access is often the bottleneck尽可能少地去访问内存
内存访问,其系统内部一般为load,store之类的指令实现,有些系统是10多个cycle,相对与寄存器变量的一般操作,如move,add,sub等,这些仅需要1个或2个cycle的操作,是比较消耗时间的
所以,如果有些变量,可能用auto自动变量替代,这尽可能少地使用calloc,malloc之类的。
unsigned byte *x, *y;
unsigned byte z;
x = (unsigned byte *) malloc(2);
y = (unsigned byte *) malloc(2); //many cycles behind malloc()
*x = …; *y = …;
…
*y += *x;
6.一些细节
Data are stored in the following preference
(1)优先考虑用以下方式存储数据:
. Stack (push, pop)
. Vector (FIFO, LIFO, Circular buffer)
. List
struct myLIST {
int att;
myLIST * next;
}
(2)List is a powerful general software concept, but
链表是一个很好的软件方面的概念
但是会有下列缺点:
. Addressing the next element normally requires memory access
对下一个元素寻址时候,需要访问内存
. Cache miss probability
容易发生cache未命中。
7.变量定义
注意由于变量定义中,由于字节对其,而出现的padding。
8.有些变量尽可能使用寄存器,有些函数,如果可以,尽量用汇编代替C实现:
比如:
extern void strcopy(char *d,const char *s)
int main
{
const char src="Source";
char dest[10];
.
.
.
strcopy(dest,src);
.
.
.
}
AREA StrCopy,CODE,READONLY
EXPORT strcopy
strcopy
LDRB R2,[R1],#1
STRB R2,[R0],#1
CMP R2,#0
BNE strcopy
MOV PC,LR
END