优化实验 Optimize

十大优化法则1.更快(本课程重点?。?
2.更?。ù娲⒖占洹⒃诵锌占洌?
3.更美(UI 交互)
4.更正确(本课程重点!各种条件下)
5.更可靠
6.可移植
7.更强大(功能)
8.更方便(使用)
9.更范(格式符合编程规范、接口规范 )
10.更易懂(能读明白、有注释、模块化)
优化概述十五种优化思路的名称,原理,实现方案

  1. 面向存储器的优化:cache无处不在
    1. 消除循环的低效率
      比如二维数组遍历运算中 , 按列枚举改为按行枚举,这是因为二维数组在内存的存储顺序是按行顺序存储的 。
    2. 重新排列提高空间局部性:尽量优先使用连续空间内的值,因为cache line 载入值时会将其附近的值一同载入分块,提高每个cache块的利用率 , 将反复多次调用的值先运算完再更新cache line,减少cache miss的次数,提高cache利用率 。
    3. 时间局部性:如果一个存储器位置被引用了一次,那么程序很可能在不远的将来重复引用它 。
    4. 空间局部性:如果一个存储器位置被引用了一次,那么程序很可能在不远的将来引用附近的一个存储器位置 。
  2. 减少过程调用
    1. 过程调用会带来开销,而且妨碍大多数形式的的程序优化 。
    2. 程序行为中严重依赖执行环境的方面 , 程序员要编写容易优化的代码 , 以帮助编译器 。
    3. 比如在字符串遍历中,每次获取字符串长度:
      for(int i = 0; i < strlen(str); i ++ ) str[i] = i;
    4. 将体量小的函数使用inline内联优化,比如min函数,max函数 。
  3. 消除不必要的内存引用
    1. 原因:存在内存别名的情况 。编译器保守的方法是不断的读和写内存,即使这样效率不高 。
    2. 引入局部变量,用局部变量计算后 , 再写入内存 。
  4. 循环展开
    1. 理解现代处理器:流水线 。
    2. 指令集并行:硬件可以并行执行多个指令 。
    3. 超标量处理器:一个周期执行多条指令,这些指令是从一个连续的指令流获取的,通常被动态调度的 。
    4. 循环展开是一种程序变换,通过增加每次迭代计算的元素的数量,减少循环的迭代次数 。
  5. 提高并行性
    1. 硬件具有更高速率执行乘法和加法的潜力,但是代码不能利用这种能力 。所以在一些计算中,我们可以将结果值拆为几个累计变量 , 提高并行性 。或者 , 重新组合变换,减少结果值的更新次数 。
    2. 多个累计变量
      在计算\(P_n=\prod_{i=0}^{n - 1}a_i\)时,可以写为\(P_n = PE_n * PO_n\)
      \(PO_n=\prod_{i=0}^{n/2 - 1}a_{2i + 1}\)\(PE_n=\prod_{i=0}^{n/2 - 1}a_{2i}\)
      /* 2 x 2 loop unrolling */void combine6(vec_ptr v, data_t *dest){ long i; long length = vec_length(v); long limit = length-1; data_t *data = https://www.huyubaike.com/biancheng/get_vec_start(v); data_t acc0 = IDENT; data_t acc1 = IDENT; /* Combine 2 elements at a time */ for(i = 0; i < limit; i+=2){acc0 = acc0 OP data[i];acc1 = acc1 OP data[i+1]; } /* Finish any remaining elements */ for(; i < limit ; i++){acc0 = acc0 OP data[i]; } *dest = acc0 OP acc1;}
    3. 重新结合变换
      /*2 * 1a loop unrolling*//*运用2×1a循环展开 , 重新结合合并操作 。这种方法增加了可以并行执行的操作数量*/void combine7(vec_ptr v, data_t *dest){ long i;long length = vec_length(v);long limit = length-1;data_t *data = https://www.huyubaike.com/biancheng/get_vec_start(v);data_t acc = IDENT;/* Combine 2 elements at a time */for (i = 0; i < limit; i+=2) {acc = acc OP (data[i] OP data[i+1]);}/* Finish any remaining elements */for (; i < length; i++) {acc = acc OP data[i];}*dest = acc;}
  6. COMVxx指令
    1. 原理:代替test/cmp+jxx,减少条件的判断,直接实现功能
    2. 实现方案:利用指令CMOVxx代替test/cmp + jxx
  7. 使用编译器的优化模式,-O:0 1 2 3
    1. 面向编译器的优化 。
    2. 期望编译器能提高速度或者能够节省内存,对程序进行有偏向性的编译 。
  8. 多线程优化
    1. 面向CPU的优化 , 利用CPU多核的性质,将任务分为多个线程
    2. 【优化实验 Optimize】多线程与多进程的区别:
      1. 线程是进程的子集,一个进程可能由多个线程组成
      2. 多进程的数据是分开的,共享复杂 。比如你可以一边听歌,一边玩游戏,实际上CPU在不断切换地工作,只是太快感觉不出来 。

        推荐阅读