void fir2(const short input[], const short coefs[], short out[])
{
int i, j;
int sum = 0;
for (i = 0; i < 40; i++)
{
for (j = 0; j < 16; j++)
sum += coefs[j] * input[i + 15 - j];
out = (sum >> 15);
}
void fir2_u(const short input[], const short coefs[], short out[])
{
int i, j;
int sum;
for (i = 0; i < 40; i++)
{
sum = coefs[0] * input[i + 15];
sum += coefs[1] * input[i + 14];
sum += coefs[2] * input[i + 13];
sum += coefs[3] * input[i + 12];
sum += coefs[4] * input[i + 11];
sum += coefs[5] * input[i + 10];
sum += coefs[6] * input[i + 9];
sum += coefs[7] * input[i + 8];
sum += coefs[8] * input[i + 7];
sum += coefs[9] * input[i + 6];
sum += coefs[10] * input[i + 5];
sum += coefs[11] * input[i + 4];
sum += coefs[12] * input[i + 3];
sum += coefs[13] * input[i + 2];
sum += coefs[14] * input[i + 1];
sum += coefs[15] * input[i + 0];
out = (sum >> 15);
}
这样虽然代码长度增加了,可变成了单循环,所有的运算都参加到pipeline中来,在Piped loop kernal 中产生每一个cycle内都使用了两个乘法器,充分利用了DSP内部的资源,提高了运行效率。又如下例:
tot = 4;
for (k = 0; k < 4; k++)
{
max = 0;
for (i = k; i < 44; i += STEP)
{
s = 0;
for (j = i; j < 44; j++)
s = L_mac(s, x[j], h[j - i]);
y32 = s;
s = L_abs(s);
if (L_sub(s, max) > (Word32) 0)
max = s;
}
tot = L_add(tot, L_shr(max, 1));
}
在这个多层循环中一共有三层循环,而最内层的循环的运算量很小,只有一次乘累加操作,而我们知道C6中一个packet中可以做两个乘累加运算,所以为了增加内部循环的运算,减少外部循环的层数,我们可以将第一层循环的操作拆开,其负责的运算加入到内部循环中,也就是在内层循环中一次做四次的乘累加运算,这样将多次操作形成pipeline,提高了运行效率,优化后的C代码如下:
tot = 4;
max0=0;
max1=0;
max2=0;
max3=0;
for (i = 0; i <44; i += STEP) //STEP=4, 11 times cirs
{
//code
for (j=0;j<=40-i;j++)
{s0=(Word32)(_sadd(s0,_smpy(hh[j],xx[j+i])));
s1=(Word32)(_sadd(s1,_smpy(hh[j],xx[j+i+1])));
s2=(Word32)(_sadd(s2,_smpy(hh[j],xx[j+i+2])));
s3=(Word32)(_sadd(s3,_smpy(hh[j],xx[j+i+3])));
}
}
//code
CCS的优化:
三、16位变为32位操作,使用intrinsic函数,用const等。