• 优化程序性能(CSAPP)


    【前言】虽然现在没有接触过大型项目,但是工作了会注重性能。学习一下,应该能更好更快的理解别人写的经典优化的代码。结合CSAPP和自己的理解,总结一下。

    一、程序优化综述

    1、高效程序的特点

      (1)适当的算法和数据结构。方法和数据的组织形式无疑是最关键的,是优化的基础;

      (2)代码能够被编译器转化成高效的可执行代码。需要深入了解使用的编译器的优化方法,和常见的优化策略;

      (3)运用现代并行编程技术。多核以及硬件支持提供更大的加速可能,例如GPU;

    2、优化程序的一般步骤

      (1)消除不必要的工作,例如消除不必要的函数调用(加大栈区负担),条件测试和内存引用;

      (2)利用处理器提供的指令级并行能力,同时执行多条指令;指令级并行介于线程级并发和单指令多数据并行之间,一个处理器可实现多指令执行,例如流水线技术;

      (3)优化关键路径。就是反复执行的数据和代码;

    二、优化编译器的能力和局限性

      我们可以使用-O1、-O2、-O3来指定编译器的优化级别,级别越高可能会增加程序的规模。注意一点,优化级别高一般比级别低的性能好,肯定比原始未优化的好!但是,编译器在优化时会考虑安全问题,如果优化一定会在安全范围内优化,有一个条件不满足就会放弃某模块的优化。

    例如:

    1 {
    2       *y += *x;
    3       *y += *x; 
    4 }
    5 //上面的代码会被优化为下面吗?
    6 {
    7     *y += 2* *x;
    8 }

    不会,虽然适用一般情况y=y+2x。但是,当x=y时:y=4x 不是3x,所以第一种不是一种好的编码,没有很好的体现编程思路。编译器会考虑所有特殊情况,保证安全。还有一种情况,是内存别名使用的时候两个变量值不同,但是指针地址有可能相同。也不会优化.

      函数调用也会妨碍优化。此时就是用内联函数优化了,避免频繁出栈入栈。

     三、优化实现方法

    发现一个别人总结的,挺全面的:http://www.xuebuyuan.com/3204184.html

    1、上面已经看到了尽量减少函数调用来降低栈压力;

    2、消除循环中的多次条件测试。举例:

    for(int i=0;i<v.size();++i)
    {
       //TODO
    }
    
    //上面和下面对比
    
    int s =v.size();
    for(int i=0;i<s;++i)
    {
       //TODO
    }

    含有循环的代码在翻译成机器级程序时,会先转换成goto语句去掉复杂逻辑,然后转换成汇编语言。所以每次都要计算测试条件,像上面这种多次计算测试条件不变的可以提前算好,赋值给局部变量,局部变量放在数据区也减轻栈的压力。如此就不要每次计算了,因为计算大小调用库函数还是需要很大的计算量的。

    3、消除不必要的内存引用

      这里主要是内存和寄存器的存取性能差别。可以将循环中的变量临时放在累加器寄存器中,计算到最后在写入内存。另一个方面,对于寄存器溢出要在栈上分配空间,也会拖慢性能,所以对寄存器数量和并发量要协调。

    4、现代处理器优化

      上面的1--3优化只是简单的降低过程调用的开销,以及消除了一些重复计算和存取瓶颈。跟、更深层次的,我们应该写出适应现代处理器架构的代码,充分发挥其性能。最基础和重要我们要理解其指令级并行,在指令级并行里面主要有两个问题:延迟界限和吞吐量界限。延迟界限指一条指令必须在另一条指令之后,吞吐量界限是硬件层面原始计算能力,是程序性能的终极限制。分支预测从软件算法层面提供延迟界限,流水线技术提高吞吐量,具体CSAPP-357

    5、循环展开

    就是在一次循环里面计算多个元素,例如下例可以将循环减半。

    //一般做法
    for(i=1;i<n;++i)
    {
        p[i]=p[i-1]+a[i];
    }
    
    //一次循环计算两个
    {int i;//全局
    for(i=1;i<n-1;i+=2)
    {
        int tmp=p[i-1]+a[i];
        p[i]=tmp;
        p[i+1]=mid+a[i+1]
    }
    if(i<n)
    {p[i]=p[i+1+a[i];]}
    }

    性能是提高了,但是可读性比较差。用在核心代码的瓶颈区比较合适。

    6、更低级优化

    并行能力提高:将一个问题拆分,最后多变量合并.。例如:将累乘分为偶数和奇数的分别累乘然后求积,偶数和奇数的计算分开并行。注意栈是线程独享的,多线程可解决一个大问题需要的栈太深的问题!

    写出针对性的分支预测算法:分支预测只对有规律的模式可行,所以可以写出更加“智能”的分支预测选择算法。根据命中率进行一个排序就能写出一个优秀的分支预测算法。结合机器学习会不会效率低?太偏上层了。

     四、综述

    优化程序性能的基本策略。

    (1)高级设计:选择合适的数据结构和算法;

    (2)基本编码原则,就是"三"中提到的;

    (3)更低级的优化:循环展开、提高指令并行度(6),重写分支预测算法。后者属于高级内容。

    更多内容参考《深入理解计算机系统CSAPP》第五章

  • 相关阅读:
    P1119 灾后重建
    P1824 进击的奶牛
    P3743 kotori的设备
    【MM配置】SAP MM模块配置目录(转)
    【SAP参数文件】SAP参数文件(转)
    【MM】供应商删除
    【Debug】修改数据库表数据的方法
    【MM 单位换算】物料基本单位换算
    EDI RFC IDOC
    【打印配置】SAP打印机配置
  • 原文地址:https://www.cnblogs.com/huangfuyuan/p/9180762.html
Copyright © 2020-2023  润新知