2014|0

6850

帖子

0

TA的资源

五彩晶圆(高级)

楼主
 

C6000编程优化方法说明 [复制链接]

C6000编译器提供的intrinsic 可快速优化C代码,intrinsic用前下划线表示同调用函数一样可以调用它,即直接内联为C6000的函数。
        例如,在上例的源代码中没有使用intrinsics,每一行C代码需多个指令周期,在改编后的代码中,每一行代码仅需一个指令周期。
        例如,“aReg_ll = (Word40)_mpyu(L_var1, L_var2) >> 16”中“_mpyu”就是一个intrinsics函数,它表示两个无符号数的高16位相乘,结果返回。C6000支持的所有intrinsics指令及其功能参见《TMS320C6000系列DSP的原理与应用》一书的第265、266页,该书还提供了另外的例子。这些内联函数定义在CCS所在的C6000 / CGTOOLS / Include目录下的C6X.h文件中。
下面这个例子是C6000的“Programmer's Guide”上提取的使用intrinsics优化C代码的例子。

源代码:
[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优化源代码。

技巧:
用内联指令_add2、_mpyhl、_mpylh完成两组16位数的加法和乘法,效率比单纯16位数的加法和乘法提高一倍。
六、if...else...语句的优化
(一)

1、源代码:

[cpp] view plain copy
if (sub(ltpg, LTP_GAIN_THR1) <= 0)//ltpgLTP_GAIN_THR1,则adapt=1  
{  
    adapt = 0;  
}  
else  
{  
    if (sub(ltpg, LTP_GAIN_THR2) <= 0)  
    {  
                    adapt = 1;  
    }  
}  
else  
{  
    adapt = 2;  
}  
2、改编后的代码:
[cpp] view plain copy
adapt = (ltpg > LTP_GAIN_THR1) + (ltpg > LTP_GAIN_THR2);  
(二)
1、源代码:
[cpp] view plain copy
if (adapt == 0)  
{  
    if (filt > 5443)  
    {  
        result = 0;  
    }  
    else  
    {  
        if (filt < 0)  
        {  
            result = 16384;  
        }  
        else  
        {  
            filt = _sshl(filt, 18) >> 16; // Q15  
            result = _ssub(16384, _smpy(24660, filt) >> 16);  
        }  
    }  
}  
else  
{  
    result = 0;  
}  
2、改编后的代码:
[cpp] view plain copy
filt1 = _sshl(filt, 18) >> 16;  
tmp = _smpy(24660, filt1) >> 16;  
result = _ssub(16384, tmp * (filt >= 0));//filt<0则result = 16384;  
result = result * (!((adapt != 0) || (filt > 5443)));//最巧妙的是,将if...else...融入表达式,adapt!=0和filt>5443任意一个条件成立result就等于0  
(三)

1、源代码:
[cpp] view plain copy
static Word16 saturate(Word32 L_var1)  
{  
    Word16 swOut;  

    if (L_var1 > SW_MAX)  
    {  
        swOut = SW_MAX;  
        giOverflow = 1;  
    }  
    else if (L_var1 < SW_MIN)  
    {  
        swOut = SW_MIN;  
        giOverflow = 1;  
    }  
    else  
        swOut = (Word16)L_var1;    /* automatic type conversion */  
    return (swOut);  
}  
2、改编后的代码:
[cpp] view plain copy
static inline Word32 L_shl(Word32 a, Word16 b)  
{  
    return ((Word32)((b) < 0 ? (Word32)(a) >> (-(b)) : _sshl((a), (b))));  
}  
3、优化方法说明:
        如果在循环中出现if...else...语句,由于if...else...语句中有跳转指令,而每个跳转指令有5个延迟间隙,因此程序执行时间延长;另外,循环内跳转也使软件流水受到阻塞。直接使用逻辑判断语句可以去除不必要的跳转。例如在例1的源代码最多有两次跳转,而改编后不存在跳转。例2和例3同样也去掉了跳转。

技巧:
        尽可能地用逻辑判断语句替代if...else...语句,减少跳转语句。


七、
1、源程序
[cpp] view plain copy
dm = 0x7FFF;  
for (j = 0; j < nsiz[m]; j = add(j, 1))//求每组数据的最小值,并把每组最小值的位置索引记录在index[m]中  
{  
    if (d[j] <= dm)  
    {  
        dm = d[j];  
        jj = j;  
    }  
}  
index[m] = jj;  
2、优化后的程序
[cpp] view plain copy
dm0 = dm1 = 0x7fff;  
d0 = (Word16 *)&d[0];  
d1 = (Word16 *)&d[1];  
# pragma MUST_ITERATE(32,256,64);  
for (j = 0; j < Nsiz; j += 2)  
{  
    n0 = *d0;  
    d0 += 2;  
    n1 = *d1;  
    d1 += 2;  
    if (n0 <= dm0)  
    {  
        dm0 = n0;  
        jj0 = j;  
    }  
    if (n1 <= dm1)  
    {  
        dm1 = n1;  
        jj1 = j + 1;  
    }  
}  
if (dm1 != dm0)  
{  
    index[m] = (dm1 < dm0) ? jj1 : jj0;  
}  
else  
{  
    index[m] = (jj1 > jj0) ? jj1 : jj0;  
}  
3、优化说明
        求数组的最小值程序,优化时为了提高程序效率在一个循环之内计算N = 1, 3, 5..和n = 2, 4, 6...的最小值,然后在比较二者的大小以求得整个数组的最小值。

八、
1、源程序

[cpp] view plain copy
for (k = 0; k < NB_PULSE; k++)  
{  
    i = codvec[k];  
    j = sign[i];  
    index = mult(i, Q15_1_5);  
    track = sub(i, extract_l(L_shr(L_mult(index, 5), 1)));  
    if (j > 0)  
    {  
        if (i < l_subfr) code[i] = add(code[i], 4096);  
        codvec[k] += (2 * L_SUBFR);  
    }  
    else  
    {  
        if (i < l_subfr) code[i] = sub(code[i], 4096);  
        index = add(index, 16);  
    }  
    if (indx[track] < 0)  
    {  
        indx[track] = index;  
    }  
    else  
    {  
        if (((index ^ indx[track]) & 16) == 0)  
        {  
            if (sub(indx[track], index) <= 0)  
            {  
                indx[track] = shl((indx[track] & 16), 3)  
                    + shr(extract_l(L_mult((indx[track] & 15), NB_POS)), 1) + (index & 15);  
            }  
            else  
            {  
                indx[track] = shl((index & 16), 3)  
                    + shr(extract_l(L_mult((index & 15), NB_POS)), 1) + (indx[track] & 15);  
            }  
        }  
        else  
    }  
    if (sub((indx[track] & 15), (index & 15)) <= 0)  
    {  
        indx[track] = shl((index & 16), 3)  
            + shr(extract_l(L_mult((index & 15), NB_POS)), 1) + (indx[track] & 15);  
    }  
    else  
    {  
        indx[track] = shl((indx[track] & 16), 3)  
            + shr(extract_l(L_mult((indx[track] & 15), NB_POS)), 1) + (index & 15);  
    }  
}  
2、优化后的程序
[cpp] view plain copy
for (k = 0; k < 8; k++)  
{  
    i = codvec[k];  
    j = sign[i];  
    index = _smpy(i, 6554) >> 16;  
    track = i - index * 5;  
    con = (j > 0);  
    codvec[k] = codvec[k] + 110 * con;  
    index = index + (!con) * 16;  
    conn = (i < l_subfr);  
    cono = (j > 0) ? 1 : -1;  
    code[i] = code[i] + 4096 * conn*cono;  
    n0 = index;  
    t0 = indx[track];  
    n1 = n0 & 16;  
    t1 = t0 & 16;  
    n2 = n0 & 15;  
    t2 = t0 & 15;  
    tmp0 = (_sshl(n1, 19) >> 16) + n2*NB_POS + t2;  
    tmp1 = (_sshl(t1, 19) >> 16) + t2*NB_POS + n2;  
    conp = (((n1 == t1) && (t0 > n0)) || ((n1 != t1) && (t2 <= n2)));  
    tmp = conp*tmp0 + (!conp)*tmp1;  
    if (t0 < 0)  
        indx[track] = n0;  
    else  
        indx[track] = tmp;  
}  
3、优化说明
        源程序中在循环中含有许多的if结构,在优化时对if结构首先进行化简,再将化简后的if结构用条件运算表达式进行改写,最后使循环可以Pipeline。


九、
1、源程序

[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语句直接求取中值。


十、
1、源程序
[cpp] view plain copy
static Word16 Bin2int(Word16 no_of_bits, Word16 *bitstream)  
{  
    Word16 value, i, bit;  

    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的数赋值。

技巧:
        充分利用C6XX一次读取32位数的特点,并利用一个指令周期能读取两个数据的特点。


十三、32bit数与16bit数相乘
1、源代码:

[cpp] view plain copy
L_tmp0 = Mac_32_16(L_32, hi1, lo1, lo2);  
2、改编代码:
[cpp] view plain copy
L_tmp0 = _sadd(_sadd(_smpyhl(hl32, lo2),(_mpyus(hl32, lo2) >> 16) << 1), L_32);  
3、优化方法说明:
        hl32是32bit的数,hi1和lo1是16bit的数,且 hl32 = hi 1<<16 + lo1 << 1 ,即hi1和lo1分别是hl32的高16位数和低16位数。函数Mac_32_16(L_32, hi1, lo1, lo2)实现L_32 = L_32 + (hi1*lo2)<<1 + ((lo1*lo2)>>15)<<1源代码是把一个32位的数拆成两个16位的数与一个16位的数相乘,优化后的代码不拆开32位的数,直接用32位的数与16位的数相乘。运用这种方法必须保证hl32的最低一位数必须为0,否则应用指令_clr(hl32, 0, 0)把最低位清零。

技巧:
       源代码中的低16位数lo1是hl32的低16位右移一位得到的(留出一位符号位)。在与lo2相乘时又右移了15位,所以在改编代码中右移16位,并且是以无符号数与lo2相乘。


十四、32bit数与32bit数相乘
1、源代码:
[cpp] view plain copy
L_tmp = Mac_32 (L_32, hi1, lo1, hi2, lo2);  
2、改编代码:
[cpp] view plain copy
L_tmp = _sadd(_sadd(_smpyh(hl1_32, hl2_32),  
((_mpyhslu(hl1_32, hl2_32) >> 16) << 1) +  
((_mpyhslu(hl2_32, hl1_32) >> 16) << 1)), L_32);  
3、优化方法说明:
        两个32位的数相乘,不必分成四个16位的数相乘,直接用32位相乘。其中:hl1_32 = hi1 << 16 + lo1 << 1, hl2_32 = hi2 << 16 + lo2 << 1;
源代码实现: L_32 = L_32 + (hi1*hi2)<<1 + ( (hi1*lo2)>>15 + (lo1*hi2)>>15 )<<1

技巧:
        低16位与高16位相乘时,低16位使用的是无符号数。


十五、16位除法的优化
1、源代码:

[cpp] view plain copy
Word16 div_s(Word16 var1, Word16 var2)  //实现 var1/var2  
{  
    Word16 var_out = 0;  
    Word16 iteration;  
    Word32 L_num = (Word32)var1;  
    Word32 L_denom = (Word32)var2;  
    for (iteration = 0; iteration < 15; iteration++)  
    {  
        var_out <<= 1;  
        L_num <<= 1;  
        if (L_num >= L_denom)  
        {  
            L_num = L_sub(L_num, L_denom);  
            var_out = add(var_out, 1);  
        }  
    }  
    return (var_out);  
}  
2、改编代码:
[cpp] view plain copy
Word16 div_s1(Word16 var1, Word16 var2)  
{  
    Word32 var1int;  
    Word32 var2int;  
    var1int = var1 << 16;  
    var2int = var2 << 15;  
    var1int = _subc(var1int, var2int);  
    var1int = _subc(var1int, var2int);  
    var1int = _subc(var1int, var2int);  
    var1int = _subc(var1int, var2int);  
    var1int = _subc(var1int, var2int);  
    var1int = _subc(var1int, var2int);  
    var1int = _subc(var1int, var2int);  
    var1int = _subc(var1int, var2int);  
    var1int = _subc(var1int, var2int);  
    var1int = _subc(var1int, var2int);  
    var1int = _subc(var1int, var2int);  
    var1int = _subc(var1int, var2int);  
    var1int = _subc(var1int, var2int);  
    var1int = _subc(var1int, var2int);  
    var1int = _subc(var1int, var2int);  
    return (var1int & 0xffff);  
}  
3、优化方法说明:
        实现16位的除法,要求被除数var1和除数var2都是整数,且var1<=var2。利用C6XX特有的指令subc,实现除法的循环移位相减操作。

技巧:
        把被除数和除数都转换成32位数来操作,返回时取低16位数。


十六、C6X优化inline举例:
1、源程序:
[cpp] view plain copy
for (i = LO_CHAN; i <= HI_CHAN; i++)  
{  

    norm_shift = norm_l(st->ch_noise[i]);  
    Ltmp = L_shl(st->ch_noise[i], norm_shift);  

    norm_shift1 = norm_l(st->ch_enrg[i]);  
    Ltmp3 = L_shl1(st->ch_enrg[i], norm_shift1 - 1);  

    Ltmp2 = L_divide(Ltmp3, Ltmp);  
    Ltmp2 = L_shr(Ltmp2, 27 - 1 + norm_shift1 - norm_shift);  // * scaled as 27,4 *  

    if (Ltmp2 == 0)  
        Ltmp2 = 1;  

    Ltmp1 = fnLog10(Ltmp2);  
    Ltmp3 = L_add(Ltmp1, LOG_OFFSET - 80807124);  // * -round(log10(2^4)*2^26 *  
    Ltmp2 = L_mult(TEN_S5_10, extract_h(Ltmp3));  
    if (Ltmp2 < 0)  
        Ltmp2 = 0;  
    // * 0.1875 scaled as 10,21 *  
    Ltmp1 = L_add(Ltmp2, CONST_0_1875_S10_21);  
    // * tmp / 0.375 2.667 scaled as 5,10, Ltmp is scaled 15,16 *  
    Ltmp = L_mult(extract_h(Ltmp1), CONST_2_667_S5_10);  
    ch_snr[i] = extract_h(Ltmp);  
}  
2、优化后程序:
[cpp] view plain copy
//因循环体太大,拆成两个循环并把相应的函数内嵌以使程序能pipeline,  
//用L_div_tmp[]保存因拆分而产生的中间变量。  
for (i = LO_CHAN; i <= HI_CHAN; i++)  
{  
    //norm_shift = norm_l(st->ch_noise[i]);  
    norm_shift = _norm(st->ch_noise[i]);  
    Ltmp = _sshl(st->ch_noise[i], norm_shift);  

    //norm_shift1 = norm_l(st->ch_enrg[i]);   
    norm_shift1 = _norm(st->ch_enrg[i]);  
    //Ltmp3 = L_shl1(st->ch_enrg[i], norm_shift1 - 1);  
    LLtmp1 = st->ch_enrg[i];  
    LLtmp1 = LLtmp1 << (norm_shift1 + 7);  
    Ltmp3 = (Word32)(LLtmp1 >> 8);  

    Ltmp2 = IL_divide(Ltmp3, Ltmp);  
    //Ltmp2 = L_shr(Ltmp2, 27 - 1 + norm_shift1 - norm_shift);   
    Ltmp2 = (Ltmp2 >> (27 - 1 + norm_shift1 - norm_shift));  

    if (Ltmp2 == 0)  
        Ltmp2 = 1;  
    L_div_tmp[i] = Ltmp2;  
}  
for (i = LO_CHAN; i <= HI_CHAN; i++)  
{  
    Ltmp2 = L_div_tmp[i];  
    Ltmp1 = IfnLog10(Ltmp2);  
    //Ltmp3 = L_add(Ltmp1, LOG_OFFSET - 80807124);   
    Ltmp3 = _sadd(Ltmp1, LOG_OFFSET - 80807124);  
    //Ltmp2 = L_mult(TEN_S5_10, extract_h(Ltmp3));  
    Ltmp2 = _smpy(TEN_S5_10, (Ltmp3 >> 16));  
    if (Ltmp2 < 0)  
        Ltmp2 = 0;  

    Ltmp1 = _sadd(Ltmp2, CONST_0_1875_S10_21);  

    //Ltmp = L_mult(extract_h(Ltmp1), CONST_2_667_S5_10);  
    Ltmp = _smpy((Ltmp1 >> 16), CONST_2_667_S5_10);  
    //ch_snr[i] = extract_h(Ltmp);  
    ch_snr[i] = (Ltmp >> 16);  
}  
3、优化说明
    观察上面这个循环,循环体本身比较大,且含有两个函数L_divide()和fnLog10(),而C62内部只有32个寄存器,且有些寄存器是系统用的,如B14、B15这样循环体太大将会导致寄存器不够分配,从而导致系统编译器无法实现循环的pipeline。

为了实现循环的pipeline。我们需要把循环体进行拆分,拆分时要考虑以下几点:
  (1)拆分成几个循环比较合适?在各个循环能pipeline的前提下,拆开的循环个数越少越好。这就要求尽可能让各个循环的运算量接近。
  (2)考虑在什么地方把程序拆开比较合适?循环体里的数据流往往并不是单一的,在拆开的断点处势必要用中间变量保存上次的循环运算结果,供以后的循环用。适当的拆开循环体,使所需的中间变量越少越好。
  (3)循环体中的函数调用必须定义成内嵌形式,含有函数调用的循环系统是无法使之pipeline的;各个循环体中的判断分支机构不可太多,否则系统也无法使之pipeline,为此应近可能把可以确定下来的分支确定下来,并尽可能用内嵌指令。  

针对上面这个例子,考虑:
  (1)为让各个循环的运算量大致相当,应把L_divide()和fnLog10()分到两个循环中去,从循环体大小上考虑,估计拆成两个循环比较合适。
  (2)考虑在什么地方把程序拆开比较合适?在if (Ltmp2 == 0) Ltmp2 = 1;后拆开,因为后面用到的数据只有Ltmp2,故只需用一个数组保存每次循环的Ltmp2值即可。
  (3)循环体中的两处函数调用L_divide()和fnLog10()都定义了其内嵌形式,IL_divid()和IfnLog10()。当把可以确定下来的分支作确定处理,并尽可能用内嵌指令后,该循环体中所剩的分支结构已很少,循环体可以pipeline。
  优化前程序用2676 cycle,优化后用400 cycle。优化后两个子循环的MII分别为14和6cycle。


内存地址形式: 奔腾,C6000都是32位计算机,字长32,但内存地址都是按字节组织的 一个字4字节(查看内存时候各个字
时候:例如两个连续字ox1000 ox1004) 写汇编程序时候,下一个字也需要+4,但写 C语言时候,int 型,+1就是加4但是,在Tiger SHARC中,虽然也是32位机,但内存是地址是按字组织的,查看内存时,连续的字地址相差1

//////////////////////////////////////////////////////////////////////////////////自己写的一段性能很高的代码///////////////////////////
[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;  
}  

 
点赞 关注

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表