优化C/C++代码的小技巧
作者:网络转载 发布时间:[ 2014/9/15 10:47:53 ] 推荐标签:软件开发 C++ 程序
16. 对于大多数的类类型,使用运算符 +=,-=,*=和/=,而少用+,-,*,/
这类简单操作其实需要创建一个匿名名的、临时的中间对象;
例如Vector v = Vector(1,0,0) + Vector(0,1,0) + Vector(0,0,1) 语句创建了5个未命名、临时的Vector:Vector(1,0,0), Vector(0,1,0),Vector(0,0,1),Vector(1,0,0) + Vector(0,1,0),以及Vector(1,0,0) + Vector(0,1,0) + Vector(0,0,1);
稍微更好点的做法:Vector v(1,0,0); v+= Vector(0,1,0); v+= Vector(0,0,1); 这样仅仅创建了2个临时Vector:Vector v(1,0,0) 和Vector(0,0,1),而节省了6个函数调用(3个构造和3个析构);
17. 对于基本数据类型,使用运算符+,-,*,/,而少用+=,-=,*=和/=
18. 延迟局部变量的定义时间
定义一个对象总会有一个函数调用开销(是构造函数)
如果一个对象只是有时候才被使用(比如在一个if语句内部),那么只在必要时才定义,因为这样只当这个变量使用时才会调用它的构造函数
19. 对于对象来说,使用前缀操作符(++obj),而不是后缀操作符(obj++)
在你的光线追踪程序中,这可能并不是个问题
对象的拷贝操作必须使用后缀操作符(这需要额外调用一个构造和一个析构函数),而前缀操作符并不产生临时对象
20. 慎用模板
各种具现化实例的优化方式可能是不同的;
标准模板库(STL)做了很好的优化,但如果你打算实现交互式光线跟踪器,好是仍避免使用;
通过自己实现,你能清楚地明白要它使用的算法,你会知道有效的使用方式;
更重要的是,我的经验表明调试、编译STL会很慢。通常这也是没问题的,除非你使用Debug版本进行性能分析。你会发现STL的构造、迭代器等操作会占用运行时间的15%以上,它会使输出的分析结果更为混乱
21. 在计算过程中避免动态内存分配
动态内存主要优势在于存储场景数据和其他数据,而不是在计算过程中进行修改
然而,在许多(大多数)时候系统动态存储分配要求使用锁来控制访问分配器。对于使用动态内存的多线程应用程序来说,由于需要等待分配和释放内存,通过这些额外的处理,你可能实际上得到的是一个更慢的程序
即使在单线程程序中,在堆上分配内存也比在栈上分配更昂贵。操作系统需要进行一些计算来确定所需大小的内存块。
22. 发现和充分利用有关你的系统内存Cache的有用信息
ü 如果一个数据结构大小恰好填满一个Cache行,处理整个类只需要从内存中读取一次;
ü 确保所有的数据结构都能对齐到Cache边界(如果你的数据大小和Cache都是128字节,那么当1个字节在一个Cache行而另外127字节在第二个Cache行时,那么性能仍然不好)
23. 避免不必要的数据初始化
如果你要初始化一大块内存,考虑用memset()函数
24. 尽量提早结束循环判断和函数返回
考虑射线和三角形相交。常见情况是射线和三角形不相交,因此这里可以优化;
如果你要判断射线和三角形相交的情况,一旦t值射线平面为负,你可以立即返回。这样可以使你跳过大约一半的光线三角形交叉点的重心坐标计算。一个巨大的胜利!一旦你确定没有相交发生,求交函数应该退出
同样的,一些循环也可以被提早结束。例如,在光线阴影设置中,近的相交是不必要的。只要发现了任何交叉闭环,求交函数可以返回
25. 先在纸上简化你使用的公式
在很多公式中,总是可以或者一些特殊情况下,可以取消计算
编译器找不到这些简化,但是你可以。消除一些内在循环中的昂贵操作可以比你在其他地方的优化更能加速你的程序
26. 对于整数型、定点数、32位浮点数、64位浮点数来说,他们之间的差别并没有你想象中的那么大
现代CPU进行浮点运算和整数运算其实有相同的运算吞吐量,像光线追踪这种计算密集型的程序,这意思是整数和浮点运算成本之间的差异可以忽略不计,这意味着你不需要做一些优化来使用整数运算;
双精度浮点运算并不一定比单精度浮点计算更慢,尤其是在64位机器上。我曾经在同一台机器上测试光线追踪算法,结果是有时全部使用double比全部使用float会运行得更快,
27. 考虑通过重写你的数学公式来消除昂贵的操作
sqrt()函数通常是可以避免的,尤其是在比较数值的平方是否相等时;
如果你需要反复除以x,考虑计算1/x,然后相乘。在向量的归一化操作中(3次除法),这曾经是一个很大的优化,但近我发现这很难说。然而如果你整除更多次数,这样做仍是有益的;
如果你执行一个循环操作,将那些在循环中固定不变的计算移出到循环外;
考虑是否能够在计算循环自增中得到值(而不是每次迭代都计算),原文:Consider if you can compute values in a loop incrementally (instead of computing from scratch each iteration).
上句改为:考虑是否可在循环中增量的计算结果,而不是在每次迭代时都重新计算(比如斐波那契数列)。该句由评论中的网友@clover_toeic所翻译。
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系SPASVO小编(021-61079698-8054),我们将立即处理,马上删除。

sales@spasvo.com