The efficiency of different C++ constructs

简介: The efficiency of different C++ constructs

循环


循环的效率取决于微处理器对循环控制分支的预测能力。一个具有一个较小并且固定的重复计数,没有分支的循环,可以完美地被预测。



循环展开


展开前

int i;
for (i = 0; i < 20; i++)
{
  if (i % 2 == 0); 
    FuncA(i);
  else
    FuncB(i);
  FuncC(i);
}

展开后

int i;
for (i = 0; i < 20; i+=2)
{
    FuncA(i);
    FuncC(i);
    FuncB(i+1);
  FuncC(i+1);
}

这样做的好处:


  • 循环次数变成了10次而不是20次,CPU可以更完美的进行预测


  • if分支被消除,有利于编译器自动进行向量化等优化


循环展开的坏处:


  • 展开循环后在代码缓存中占用更多空间


  • 非常小的循环展开不如不展开


  • 如果重复计数为奇数,并将其展开为2, 则必须在循环之外执行额外的迭代。

只有在能够取得特定好处的情况下,才应该使用循环展开。如果一个循环包含浮点运算,且循环计数器是整数,那么通常可 以假设整个计算时间是由浮点代码决定的,而不是由循环控制分支决定的。在这种情况下,展开循环是没有任何好处的 。



循环控制条件


如果循环控制分支依赖于循环内部的计算,则效率较低。


确定最坏情况下的最大重复计数并始终使用此迭代次数的效率会更高。


循环计数器最好是整数。



复制或清除数组


对于诸如复制数组或将数组中的元素全部设置为零这样的琐碎任务,使用循环可能不是最佳选择。使用memset和memcpy函数通常会更快



函数


函数调用会让程序慢下来,因为


  • 代码地址跳转,可能需要4个时钟周期



  • 如果代码分散在内存中会降低代码缓存效率


  • 如果函数参数不够放在寄存器中,需要入到栈中,效率不高


  • 需要额外时间设置stack frame, 保存和恢复寄存器


  • 每个函数调用语句需要在分支目标缓冲区(BTB)中占用空间 , BTB争用可能会导致分支预测失败



如何避免函数调用降低效率呢?



避免不必要函数


不要过度封装


使用内联函数


如果函数很小,或者只在程序中的一个位置调用它,那么内联函数是有好处的。小函数通常由编译器自动内联


避免在最内层循环嵌套函数调用


如果程序关键的最内层循环包含对帧函数的调用,那么代码有可能通过内联帧函数或使帧函数调用的所有函数内联(把帧函数变为叶函数)来提升效率


使用宏代替函数


但是不要滥用宏,宏的问题是:名称不能重载或限制作用区域。宏将干扰具有相同名称的任何函数或变量,而与作用域或命名空间无关


使函数局部化


应该使同一个模块中使用的函数(即当前*.cpp* 文件)是局部的。 这使得编译器更容易将函数内联,并对函数调用进行优 化。


如何使函数局部化呢?


  • 对于非类成员函数,直接使用static


  • 对于类成员函数,将函数或类放置于匿名命名空间中


使用全程序优化


一些编译器具有对整个程序进行优化的选项,也可以选择将多个 .cpp 文件组合成一个对象文件。这使得编译器能够在组成程 序的所有 .cpp 模块之间优化寄存器分配和参数传递。


使用64位模式


现在服务器端开发都是64位模式了吧


相关文章
|
存储 缓存 并行计算
The efficiency of different C++ constructs5
The efficiency of different C++ constructs5
192 0
|
存储 缓存 编译器
The efficiency of different C++ constructs4
The efficiency of different C++ constructs4
197 0
|
缓存 安全 编译器
The efficiency of different C++ constructs3
The efficiency of different C++ constructs3
204 0
|
存储 缓存 Unix
The efficiency of different C++ constructs2
The efficiency of different C++ constructs2
201 0
|
9月前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
5月前
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
156 0
|
5月前
|
存储 编译器 程序员
c++的类(附含explicit关键字,友元,内部类)
本文介绍了C++中类的核心概念与用法,涵盖封装、继承、多态三大特性。重点讲解了类的定义(`class`与`struct`)、访问限定符(`private`、`public`、`protected`)、类的作用域及成员函数的声明与定义分离。同时深入探讨了类的大小计算、`this`指针、默认成员函数(构造函数、析构函数、拷贝构造、赋值重载)以及运算符重载等内容。 文章还详细分析了`explicit`关键字的作用、静态成员(变量与函数)、友元(友元函数与友元类)的概念及其使用场景,并简要介绍了内部类的特性。
239 0
|
7月前
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
281 12
|
8月前
|
设计模式 安全 C++
【C++进阶】特殊类设计 && 单例模式
通过对特殊类设计和单例模式的深入探讨,我们可以更好地设计和实现复杂的C++程序。特殊类设计提高了代码的安全性和可维护性,而单例模式则确保类的唯一实例性和全局访问性。理解并掌握这些高级设计技巧,对于提升C++编程水平至关重要。
171 16
|
9月前
|
编译器 C语言 C++
类和对象的简述(c++篇)
类和对象的简述(c++篇)