C++性能之战(7)--一些凑不成一篇文章的C++优化技巧

0. 写在最前面

本文持续更新地址:https://haoqchen.site/2020/07/11/some-cpp-optimize/

有一些比较小的优化技巧,凑不成一篇文章,在这里做个记录。

如果觉得写得还不错,可以找我其他文章来看看哦~~~可以的话帮我github点个赞呗。
你的Star是作者坚持下去的最大动力哦~~~

1. Strength reduction

译作强度折减?这是编译器的优化技术,现在一般的编译器都已经能够自动识别,不需要我们自己实现。但有些比较老,或者功能不强的编译器还是最好自己整一下。

这个概念诞生是因为不同指令在CPU中的执行时间是不一样的,比如乘法的执行时间就远远大于移位,乘法也远远大于加法。那自然就有人会想将乘法这种高强度的计算转换成移位或者加法。

1.1 基本运算

以下是一些可以进行Strength reduction的操作,引自维基百科:
在这里插入图片描述
目前常见的编译器应该都会对操作数是2^n的进行优化,但其他的不太敢保证。实在不放心可以自己优化,记得很早前做单片机的时候,那些编译器就真的需要自己优化,否则分分钟不够时间。

1.2 浮点数除法转乘法

这里有一点值得提醒,同一类型乘法占用的CPU时间是比除法要少的,所以能写乘法就不要写除法。

快到什么程度呢,1个除法比3个乘法还要耗时,即使是开了O2优化:

详细代码请参考github中的strength_reduction.cpp

// (1)两次除法,一次加法
mul.start();
for (int j = 0; j < i; ++j){
    result[j] = a1[j] / b1[j] + a2[j] / b2[j];
}
mul.stop();
// (2)一次除法,一次加法,三次乘法
result.clear();
plus.start();
for (int j = 0; j < i; ++j){
    result[j] = (a1[j] * b2[j] + a2[j] * b1[1]) / (b1[j] *b2[j]);
}
plus.stop();

在这里插入图片描述

2. 用空间换时间

这个最常见的就是先进行预计算,然后存到数组中备用。比如sincos,在机器人以及定位建图等经常会用到,而他们耗时又非常多,我们可以搞个36000大小的数组,预先计算好sin的值,0.01度的分辨率已经能满足大多数人对精度的要求了。

但也有人指出,使用lookup table的方式时,内存读取有时会比重新计算还要耗时,尤其是多线程存在race condition时。

3. 减少临时对象的产生

3.1 多使用+=、-=、*=和/=

int a = 0;
a = 10 + a; // 有临时变量产生

a += 10; // 无临时变量产生

3.2 理清赋值与构造的区别

std::string s3_1; 
s3_1 = s1 + s2; // 此处是先构造再赋值,产生临时对象,这是最差的代码

std::string s3_2 = s1 + s2; // 此处是直接构造,产生临时对象,次好

std::string s3_3(a);
s3_3 += b; // 不产生临时变量,最好

3.3 使用std::move充分利用临时变量

当某个临时变量后面不需要再用到时,可以在赋值或emplace_back时使用std::move将其变为右值,这样能减少一次析构和一次构造,让临时变量得到充分利用。

4. 延迟声明局部变量

这是C++相对于C的改进,C的函数中,变量的定义必须放在最开头,但C++的变量定义可以放在函数的任意地方,甚至可以放在return前(虽然没什么用)。延迟声明的意思是要用到再声明,这样就只会在用到时再声明,没用到时就省了。

参考


喜欢我的文章的话Star一下呗Star

版权声明:本文为白夜行的狼原创文章,未经允许不得以任何形式转载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值