源代码:
[cpp] view plain copy
int dotprod(const short *a, const short *b, unsigned int N)
{
int i, sum = 0;
for (i = 0; i < N; i++)
sum += a[i] * b[i];
return sum;
}
改编后代码:
[cpp] view plain copy
int dotprod(const int *a, const int *b, unsigned int N)
{
int i, sum1 = 0, sum2 = 0;
for (i = 0; i < (N >> 1); i++)
{
sum1 += _mpy(a[i], b[i]);
sum2 += _mpyh(a[i], b[i]);
}
return sum1 + sum2;
}
技巧:
在C语言的调试全部通过以后,可以尝试将尽可能多的语句使用intrinsics函数加以改编,尤其在循环体内,这种改编可以大幅度减少执行时间。
四、
1、源代码:
[cpp] view plain copy
void fir_fxd1(short input[], short coefs[], short out[])
{
int i, j;
for (i = 0; i < 40; i++)
{
for (j = 0; j < 16; j++)
out[i * 16 + j] = coefs[j] * input[i + 15 - j];
}
}
2、改编后的代码:
[cpp] view plain copy
void fir_fxd2(const short input[], const short coefs[], short out[])
{
int i, j;
for (i = 0; i < 40; i++)
{
for (j = 0; j < 16; j++)
out[i * 16 + j] = coefs[j] * input[i + 15 - j];
}
}
3、优化方法说明:
C6000编译器如果确定两条指令是不相关的,则安排它们并行执行。 关键字const可以指定一个变量或者一个变量的存储单元保持不变。这有助于帮助编译器确定指令的不相关性。例如上例中,源代码不能并行执行,而结果改编后的代码可以并行执行。
技巧:
使用const可以限定目标,确定存在于循环迭代中的存储器的不相关性。
五、
1、源代码:
[cpp] view plain copy
void vecsum(short *sum, short *in1, short *in2, unsigned int N)
{
int i;
for (i = 0; i < N; i++)
sum[i] = in1[i] + in2[i];
}
2、改编后的代码:
[cpp] view plain copy
void vecsum6(int *sum, const int *in1, const int *in2, unsigned int N)
{
int i;
int sz = N >> 2;//用int型读取short数据,循环次数减半
_nassert(N >= 20);
for (i = 0; i < sz; i += 2)//循环展开i每次加2
{
sum[i] = _add2(in1[i], in2[i]);
sum[i + 1] = _add2(in1[i + 1], in2[i + 1]);
}
}
3、优化方法说明:
源代码中,函数变量的定义是 short *sum, short *in1, short *in2, 改编后的代码函数变量是int *sum, const int *in1, const int *in2, 整数类型由16位改编成32位,这时使用内联指令“_add2”一次可以完成两组16位整数的加法,效率提高一倍。注意这里还使用了关键字const和内联指令_nassert优化源代码。
[cpp] view plain copy
for (i = 0; i < n; i++)
{
max = -32767;
for (j = 0; j < n; j++)
{
if (sub(tmp2[j], max) >= 0)
{
max = tmp2[j];
ix = j;
}
}
tmp2[ix] = -32768;
tmp[i] = ix;
}
2、优化后的程序
[cpp] view plain copy
if (n0>n1) {temp=n0;n0=n1;n1=temp;}
if (n1>n2) {temp=n1;n1=n2;n2=temp;}
if (n2>n3) {temp=n2;n2=n3;n3=temp;}
if (n3>n4) {temp=n3;n3=n4;n4=temp;}
if (n0>n1) {temp=n0;n0=n1;n1=temp;}
if (n1>n2) {temp=n1;n1=n2;n2=temp;}
if (n2>n3) {temp=n2;n2=n3;n3=temp;}
if (n0>n1) {temp=n0;n0=n1;n1=temp;}
if (n1>n2) {return n1;}
3、优化说明
源程序也为一个求中值的问题,由于已知循环次数固定为5,因此将循环展开使用if语句直接求取中值。
value = 0;
for (i = 0; i < no_of_bits; i++)
{
value = shl(value, 1);
bit = *bitstream++;
if (sub(bit, BIT_1) == 0)
value = add(value, 1);
}
return (value);
}
for (i = 0; i < prmno[mode]; i++)
{
prm[i] = Bin2int(bitno[mode][i], bits);
bits += bitno[mode][i];
}
2、优化后的程序
[cpp] view plain copy
value = 0;
bitsp = bits;
bitnop= &bitno[mode][0];
j = *bitnop++;
j1 = *bitnop++;
j2 = *bitnop++;
j3 = *bitnop++;
j4 = *bitnop++;
_nassert(loop[mode]>=35);
for (i = 0; i < loop[mode]; i++)
{
value = value * 2 + *bitsp++;
j--;
if (j == 0)
{
*prm++ = value;
value = 0;
j = j1;
j1 = j2;
j2 = j3;
j3 = j4;
j4 = *bitnop++;
}
}
3、优化说明
源程序按照数据位流定义取出参数,为双重循环结构,优化中采用重新根据位流的bit长度定义循环次数,化简为单重循环,然后优化循环,去除boundary,使pipeline的数目最小。
十一、copy程序的优化
1、源代码:
[cpp] view plain copy
Word16 i;
for (i = 0; i < L; i++)
{
y[i] = x[i];
}
2、改编代码:
(1)要求数组长度能被2整除
[cpp] view plain copy
Word32 i;
Word32 temp;
int *p1 = (int *)&x[0];
int *q1 = (int *)&y[0];
for (i = 0; i < L / 2; i++)
{
temp = *p1++;
*q1++ = temp;
}
(2)要求数组长度能被4整除
[cpp] view plain copy
Word32 i;
Word32 temp1, temp2;
Word32 *pin1, *pin2, *pout1, *pout2;
pin1 = (Word32 *)&x[0];
pin2 = (Word32 *)&x[2];
pout1= (Word32 *)&y[0];
pout2= (Word32 *)&y[2];
for (i = 0; i < L / 4; i++)
{
temp1 = *pin1;
temp2 = *pin2;
pin1 += 2;
pin2 += 2;
*pout1 = temp1;
*pout2 = temp2;
pout1 += 2;
pout2 += 2;
}
3、优化方法说明:
把一次循环拷贝一个word16的数改为一次循环拷贝2个word16或4个word16的数。
技巧:
充分利用c6xx一次读取32位数的特性,并利用一个指令周期能读取两个数据的特点。
十二、set_zero程序的优化
1、源代码:
[cpp] view plain copy
Word16 i;
for (i = 0; i < L; i++)
{
x[i] = 0;
}
2、改编代码:
(1)数组长度能被2整除
[cpp] view plain copy
Word32 i;
int *x1 = (int *)&x[0];
for (i = 0; i < L / 2; i++)
{
*x1++ = 0;
}
(2)数组长度能被4整除
[cpp] view plain copy
Word32 i;
int *x1 = (int *)&x[0];
int *x2 = (int *)&x[2];
for (i = 0; i < L / 4; i++)
{
*x1 = 0;
*x2 = 0;
x1++;
x2++;
x1++;
x2++;
}
3、优化方法说明:
把一次循环为一个word16的数赋值改为一次为2个或4个word16的数赋值。
//////////////////////////////////////////////////////////////////////////////////自己写的一段性能很高的代码///////////////////////////
[cpp] view plain copy
#include
#define INTRINSIC
short add(short var1, short var2)
{
short var_out;
int L_somme;
L_somme = (int)var1 + var2;
return(var_out);
}
int main()
{
int i, result;
#ifdef INTRINSIC
for (i = 0; i<1000; i++)
{
result = _sadd(100000, 20);
result>0X00007fff ? result = 0x7fff : (result < 0x8000 ? result = 0x8000 : 0);
}
#else
for (i = 0; i < 1000; i++)
add(10, 20);
#endif
return 0;
}