如何写出让 CPU 跑得更快的代码?
————NEOHOPE的代码优化手册
一、需求阶段
1、过早优化是魔鬼。业务能运行,比业务响应速度更重要。能用的慢代码,比不能用的快代码好的多
2、搞清楚业务类型,是重IO,还是重CPU,还是重GPU,明确具体需求
3、这个需求,确定是要通过代码优化解决吗?
是不是一个业务问题无法解决,想通过系统去限制业务呢?
4、这个需求,是否可以通过花钱或其他方式解决,比如增加硬件
5、搞清楚为何要优化代码,不优化问题是什么?优化代码的风险是什么?时间周期大概是剁手?代价和受益如何?
6、对比4、5的各种方案,确定用哪个
二、分析阶段
1、一旦明确了要进行优化,不要一头扎入细节。考虑整个系统的架构是否合理,看下全局,看下上下游的影响。
2、遵从Ahmdal定律,确定优化范围;
3、咱们要优化的东西,业界是否已有解决方案,不要重复造轮子
4、如果涉及面比较广,别急着动手,做好分析,制定方案,再动手
三、架构阶段
1、调整不合理的架构
2、调整不合理的数据流
3、进行必要的组件替换
四、算法提升阶段
1、遵从80-20法则,程序80%的时间在运行20%或更少的代码,针对热代码进行优化,才容易产出效果;
2、评估当前算法,是否有高效的算法
比如:用DP或贪婪算法替代暴力算法,将算法的时间复杂度尽量降低
3、使用合理的数据结构
比如哈希表、红黑树
4、使用数学公式,替代低效计算
5、缓存重复出现的中间结果,空间换时间
五、编码提升阶段
1、遵从数据访问的局部性法则,按数据存放顺序访问内存效率远高于乱序访问内存效率,也就是尽量帮助CPU做好数据Cache的预测工作。同样根据Cache大小,做好数据结构的优化工作,进行数据压缩或数据填充,也是提升Cache效率的好方式;
2、遵从指令访问的局部性法则,减少跳转指令,同样是尽量帮助CPU做好数据Cache的预测工作;现代CPU都有一些预测功能【如分支预测】,利用好CPU的这些功能,也会提升Cache命中率;
3、减少内存的重复申请和释放
4、 减少函数调用层数
使用INLINE等关键字,同样是减少调用层数
使用宏展开,也有类似效果
5、减少数据传递个数,合理封装
6、数据传递,以引用为主,减少传值
7、减少数据类型转换
10、调整运算顺序,减少CPU低效运算。
比如除法运算。
11、调整运算顺序,尽早结束循环,避免无效操作
12、 少用高级语言的多重继承等特性
13、使用汇编和C语言,而不是更高级的语言,很多时候可以提速运算效率;
14、直接使用昂贵的寄存器作为变量,可以变相提供加速效果;
15、采用性能高的函数,批量处理数据,如memset等
16、能在编译阶段完成的任务,不要留到运行阶段完成。
比如,CPP的泛型是编译阶段完成的,比运行时再做处理的语言效率更高
比如,不要用反射,不要动态类型绑定
比如,初始化工作尽早完成
六、编译阶段
1、开启编译器优化,速度最大化
2、使用Intel自家的编译器,开启性能优化,很多时候可以提速运算效率;
3、考虑指令级并行性(IPL)
七、运行阶段
1、避免计算线程在多个核心之间漂移,避免缓存重复加载,可以绑定核心【物理核即可,不用到逻辑核】,提高效率;
2、去除伪共享缓存:在多核环境下,减少多个核心对同一区域内存的读写并发操作,减少内存失效的情况的发生;
3、合理提高进程优先级,减少进程间切换,可以变相提供Cache提速的效果;
4、关闭Swap,可以变相提供内存提速、Cache提速的效果;
八、测试阶段
1、合适的手段及工具进行性能评估
2、要符合实际情况,不要片面追求指标
先总结这些吧。