美文网首页
优化程序性能

优化程序性能

作者: 索马里的海带 | 来源:发表于2018-04-12 17:36 被阅读0次

        个人觉得虽然没必要过度优化,现代编译器在优化方面已经做得比较好了,但是在有些方面,还是需要程序员主动去做的。

        不过度优化≠不主动优化

        深度学习跑模型的时候,有时候可能一跑就是几天,哪怕只对程序优化10%,效果也是非常可观的。在进行优化的时候,程序可能因此可读性和可维护性都变差,这就需要程序员自己去权衡了,在速度非常重要的时候,做一些牺牲也是可以接受的。

    1.高级设计。为遇到的问题选择适当的算法和数据结构。要特别警觉,避免使用那些会渐进产生糟糕性能的算法和编码技术。

    2.基本编码原则。避免限制优化的因素,这样编译器就能产生高效的代码。

        这点是非常重要的,因为其他优化编译器都可以代替你做,但是以下两点,编译器是没办法做优化的,至于为什么这两点会导致编译器没办法优化,这里不再赘述。

    1)消除连续的函数调用。在可能时,将计算移到循环外。考虑有选择性的妥协程序的模块性已获得更大的效率。 

        除此之外,在可能的情况下,使用内联函数也是一个很好的选择。

        举个例子:

        在C++11以前,容器成员函数size()都是O(n),如果采用以下写法,原本O(n)复杂度的代码就变成了O(n^2)。

        for (int i=0;i<str.size();i++)

        正确的做法是尽量将函数调用提到循环外。

    2)消除不必要的存储器引用。引入临时变量来保存中间结果。只有在最后的值计算出来时,才将结果放到数组或全局变量中。

        这个应该很好理解,学过计算机组成原理的都知道存储器速度远低于寄存器速度。

    3.低级优化 

    1)展开循环,降低开销,并且使得进一步的优化成为可能。 

        现代编译器一般都会进行循环展开优化,但是碰到严重限制程序速度的代码,还是可以尝试用循环展开改进速度。

    2)通过使用例如累积变量和重新结合等技术,找到方法提高指令级并行。 

        ①累计变量

        例如a1*a2*a3*a4

        可以改成求(a1*a2)*(a3*a4)

        如果用分治法,可以把原本O(n)复杂度减少到O(logn)

        ②重新结合

        那么重新结合是意思呢,看以下代码:

        int    a=0,b=1,c=3;

        第一种写法:    a=a+b+c;

        第二种写法:    a=a+(b+c);

        乍一看这两种写法没什么区别,但是实际上两种代码的关键路径是不一样的。在汇编代码中,关键路径限制代码执行代码执行速度。

        第一种写法,应该先将a+b保存在寄存器c中,即存在寄存器写后读相关,指令不能并行执行。但是第二种写法,b+c保存在不同寄存器中,两条乘法指令互相不影响。

        以前学计算机组成原理的时候,这种冲突可以通过记分牌算法和Tomasulo算法解决,但是让硬件去优化,还是会增加开销。我用clang试了一下,编译器也是会做此类优化的。所以一般情况下,这类优化并没有太大必要。

    3)使用功能的风格重写条件操作,使得编译采用条件数据传送。

        C++中在可能的情况下,用三目运算符 ?:代替条件语句。(条件传送指令更快)

    相关文章

      网友评论

          本文标题:优化程序性能

          本文链接:https://www.haomeiwen.com/subject/qlqtkftx.html