C++性能优化一些知识点
1. 整数用 >>或者<<,代替乘除法,用&代替 %
2. 乘法 > 除法 ,相同的除数,可以先计算倒数,然后乘法,除法可以转换成乘法,/2 =》 *0.5
3. 乘法 > pow
4. 两元比较 用 ?: 代替max,min函数,
5. ++i > i++i++开辟了临时变量,效率低
6. 将小粒度函数申明为内联函数
减少函数调用: 函数调用需要两次跳转和外栈帧的内存操作
7.迭代 > 递归
8. vector取值,[]>at, 指针的寻址p+i > 数组下标取值[i]
9. 大小尽量往 2^n 上靠,可以用逻辑运算符替换普通运算
x%y === x - (x/y)*y. 假如: y = 2^n 比如 x % y <==> x & (y -1)
10. 局部变量 > 静态变量
11. 数组的能不初始化就不用初始化。
12. 可以存储中间计算结果,减少重复计算,必要时可以用查表代替反复复杂计算
13. 临时变量定义尽量有序,大内存在前,小内存在后,尽量内存对齐
14. if分支放到 for的外面,减少再for循环中判断
15. 比较大小的时候尽量做到同类型的比较, 例如unsigned int和 int比较会损耗性能
16. 使用直接初始化代替复制初始化 ClassTest ct2(ct1); //直接初始化
17. 避免过大的循环:
for(inti = 0; i < n; ++i)
{
fun1();
fun2();
}
如果fun1和fun2的代码量很大,例如都大于Cache的容量,则在代码1中,就不能充分利用Cache了(由时间局部性和空间局部性可知),因为每循环一次,都要把Cache中的内容踢出,重新从内存中加载另一个函数的代码指令和数据,而代码2则更很好地利用了Cache,利用两个循环语句,每个循环所用到的数据几乎都已加载到Cache中,每次循环都可从Cache中读写数据,访问内存较少,速度较快,理论上来说只需要完全踢出fun1的数据1次即可
18. 在内存中存取一个变量最高效的方式是将其放在一个可以被它的长度整除的地址上。
(void *)&variable % sizeof(variable) == 0
19. 构造函数返回值 > 定义临时对象,return 临时对象 return C(i,j,k); > C c; c = func(i,j,k); return c;
20. for循环,次数少的在外面,次数多是子循环,可能因为机器的原因出现相反的现象
21. 在消息通信系统中,系统调用的数量太多的话会导致出现性能瓶颈。实际上,这个问题绝非一般。当需要遍历调用栈时会有不小的性能损失,因此,明智的做法是,当创建高性能的应用时应该尽可能多的去避免遍历调用栈。
22. 利用CPU的无序性,必须避免长依赖链,充分利用加法和浮点计算执行单元,浮点数计算可以平衡的混合加法和乘法。
23. 合适的算法,简单算法代替复杂高级的算法,小数据链表不需要用哈希表,遍历也无需二分法
24. 去掉不必要的函数;
25.尽量使用inline
26. 避免在最内循环嵌套调用函数;
27.使用宏替代一些函数;
28. 使用fastcall和vectorcall函数
29. 去掉虚拟使用,不使用动态内存
编译选项:GCC 编译开关 -O1 ~ -O3 替代 默认的-O0,关闭RTTI
一些测试代码性能的工具:
Java的JProfiler/TPTP/CodePro Profiler,GNU的gprof,IBM的PurifyPlus,Intel的VTune,AMD的CodeAnalyst,还有Linux下的OProfile/perf,后面两个可以让你对你的代码优化到CPU的微指令级别,如果你关心CPU的L1/L2的缓存调优,那么你需要考虑一下使用VTune。 使用这些Profiler工具,可以让你程序中各个模块函数甚至指令的很多东西,如:运行的时间 ,调用的次数,CPU的利用率
~~如果以上内容能够对你有所帮助并引起你的一点点思考,可以请作者喝一杯咖啡。