[开发工具]探讨Keil中优化等级与运行效率关系

    在软件开发中,编译器优化选项是提高程序执行效率的关键工具。特别是在嵌入式系统开发中,不同编译器的优化选项可以对代码的性能产生显著影响,本文将探讨Keil编译器中不同优化等级对代码执行效率的关系。
## Keil优化等级说明
  Keil编译器的优化等级是编译过程中一个重要的设置,它可以显著影响程序的性能和大小。
  为什么需要进行编译优化?
  进行编译优化是为了提高程序的性能和效率。编译优化的主要用途包括:
    - 提高执行速度:通过优化代码,减少程序运行时的指令数量,从而加快程序的执行速度。
    - 减少内存占用:优化可以帮助减少程序的大小,降低对内存的需求,这在资源受限的嵌入式系统中尤为重要。
    - 电源管理:优化后的代码可以更有效地使用处理器资源,这有助于降低能耗,延长电池寿命。
    - 提高可靠性和稳定性:优化可以消除代码中的冗余和不必要的部分,有助于提高程序的稳定性和可靠性。
  Keil有几个不同的优化等级:
    - O0这是无优化等级,编译器不会尝试优化代码。这对于调试非常有用,因为生成的代码会非常接近你的原始代码,使得跟踪和理解程序的行为变得容易。
    - O1这个等级提供了基本优化。编译器会尝试不影响代码可读性的前提下,进行一些基本的性能改进。
    - O2在这个等级,编译器会进行更多的优化,如代码重排和循环优化,以提高执行速度和减少代码大小。
    - O3这是最高的优化等级,编译器会尝试所有可能的优化技术来提高程序的运行效率,即使这可能会增加代码的大小。

## 测试环境:
    开发板:APM32F407
    主频:168MHz

### 1.Test_add测试
    一个简单的加法运算。
核心代码:
复制
void add(u32 n)

{

    u32 a = 0, b = 0;

    while (n-- > 0)

    {

        a = b + n;

    }

}



//执行100000次

void test_add(void)

{

    u32 n = 100000;



    while (n-- > 0)

    {

        add(100000);

    }



    return;

}

测试结果:
    如下图是依次选择-O0,-O1,-O2,-O3得到的代码执行时间。


 

### 2.Test_FFT测试
    这是一个较复杂的运算,FFT代表快速傅里叶变换。
核心代码:
复制
#define PI 3.14159265358979323846

#define N 1024 // 定义FFT的点数



typedef struct

{

    double real;

    double imag;

} complex32;



//typedef unsigned int u32;



int count = 0;



// 位反转置换函数

void bitReversal(complex32 *pSrc, u32 n)

{

    u32 i, j, k;

    for (i = 1, j = 0; i < n; i++)

    {

        for (k = n >> 1; k > (j ^= k); k >>= 1)

        {

        }

        if (i < j)

        {

            complex32 temp = pSrc[i];

            pSrc[i] = pSrc[j];

            pSrc[j] = temp;

        }

    }

}



// 迭代FFT函数

void iterativeFFT(complex32 *pSrc, u32 n)

{

    // 预先计算Wn数组

    complex32 *Wn = (complex32 *)malloc(sizeof(complex32) * n / 2);

    for (u32 i = 0; i < n / 2; i++)

    {

        Wn[i].real = cos(2 * PI * i / n);

        Wn[i].imag = -sin(2 * PI * i / n);

    }



    // 位反转置换

    bitReversal(pSrc, n);



    // FFT主循环

    for (u32 s = 1; s <= log2(n); s++)

    {

        u32 m = 1 << s;

        u32 m2 = m >> 1;

        complex32 w;

        w.real = 1.0;

        w.imag = 0.0;

        for (u32 j = 0; j < m2; j++)

        {

            for (u32 k = j; k < n; k += m)

            {

                u32 t = k + m2;

                complex32 u = pSrc[k];

                complex32 v;

                v.real = w.real * pSrc[t].real - w.imag * pSrc[t].imag;

                v.imag = w.real * pSrc[t].imag + w.imag * pSrc[t].real;

                pSrc[k].real = u.real + v.real;

                pSrc[k].imag = u.imag + v.imag;

                pSrc[t].real = u.real - v.real;

                pSrc[t].imag = u.imag - v.imag;

            }

            complex32 wn = Wn[n / m * j];

            w.real = w.real * wn.real - w.imag * wn.imag;

            w.imag = w.real * wn.imag + w.imag * wn.real;

        }

    }

    free(Wn);

}

测试结果:
    如下图是依次选择-O0,-O1,-O2,-O3得到的代码执行时间。

### 测试数据对比:
  
优化等级
  
Test_add(单位:秒)
Test_fft(单位:秒)
-O0
298.978190
68.000412
-O1
239.971474
62.022487
-O2
179.987680
61.009636
-O3
179.987680
61.985575

### 测试数据分析:
    - 对于简单的加法操作(test_add),随着编译优化等级的提升,执行时间显著减少。特别是从 -O0 到 -O1 ,以及从 -O1 到 -O2,我们看到了明显的性能提升。然而,从 -O2 到 -O3,性能提升不再明显,执行时间保持不变,这表明对于简单运算,-O2 已经足够优化。
    - 对于复杂的运算,如快速傅里叶变换(test_fft),优化等级的提升同样带来了性能的提升,但提升幅度相对较小。从 -O0 到 -O1 有一定的性能提升,而从 -O1 到 -O2,我们看到了最佳的执行时间,但从 -O2 到 -O3,执行时间反而略有增加。
    打个简单的比方,当你让电脑做一些非常基本的事情,比如简单的加法,提高编译器的优化水平就像是给电脑喝了能量饮料,它会变得更快。但是,就像人在喝了太多能量饮料后不会变得更聪明一样,电脑在处理复杂的数学问题时,即使优化了,也不会有太大的提升。这是因为复杂的问题本身就很难处理,就像是需要解决一个超级难的数独谜题,而不仅仅是数数那么简单。
    所以,当你让电脑做更复杂的事情,比如快速傅里叶变换(一种复杂的运算),即使你给它更多的能量饮料(也就是更高级的优化),它也只能快那么一点点。因为这时候,电脑不仅要算数,还要记住很多东西,还要做很多决定,这些都会让它慢下来。
    总之,让电脑做简单的事情时,优化可以大大提高速度。但是对于复杂的任务,优化帮助不大,因为任务本身就很难。

## 总结
    总的来说,随着编译优化等级的提高,简单和复杂的运算都有性能提升,但简单运算的提升更为显著。这可能是因为编译器优化更容易对简单的重复操作进行优化,如循环展开、指令重排等。而对于复杂运算,尽管优化也有帮助,但由于算法本身的复杂性,优化空间可能不如简单运算那么大。此外,复杂运算可能涉及更多的内存访问和分支预测,这些因素也会影响优化的效果。

    附件为该测试的工程源码,有需要的可自行下载。

 Compilation_Optimization.zip (788.06 KB)。
---------------------
作者:DKENNY
链接:https://bbs.21ic.com/icview-3385800-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值