C++编译器是否优化了顺序静态变量读取?
Do C++ compilers optimize sequential static variable reading?
当通过 const ref 访问函数作用域中同一静态变量时,C++编译器是否优化了该变量的顺序读数?因此,CPU 只会从静态数据中的地址读取一次其值,然后将该值存储在 CPU 缓存内存中并重用它,假设该值是不可变的?换句话说:静态变量是否隐式声明为易失性,就像有其他线程一样,值可能会神奇地改变?
因为如果 CPU 不会缓存该值,则来自静态变量地址的顺序读数可能会损害性能。在这种情况下,手动复制堆栈上的变量中的值以便将其置于 CPU 缓存中是否更好?
class Singleton
{
// some code
Data data;
public:
static Singleton& instance()
{
static Singleton inst;
return inst;
}
}
int func(const Data& param);
int foo(int N)
{
int result = 0;
for (int i = 0; i < N; ++i)
{
// will compiler move the reading outside of the loop and the value will be cached by CPU?
const auto& data = Singleton::instance().data;
result += func(data);
}
return result;
}
如果编译器能够毫无疑问地证明该值在不同访问之间不会改变,那么根据 as-if 规则,它可以将多个读取合并为一个。
但是,使用具有静态存储持续时间的变量通常很难证明它,因为其他翻译单元(在您的示例中func()
(中可能存在修改它的代码。因此,在看不到func()
做什么的情况下,编译器被迫在每次迭代中重新加载data
。同样,当编译func()
本身时,每次都需要重新加载其参数。
然后也可能有其他线程修改data
.根据C++内存模型规则,这些更改在同步事件(可以是内存围栏、互斥锁或原子获取/释放等(之前不必变得可见。
所以是的,缩小变量的范围通常会导致性能的提高。证明局部变量不能从"外部"修改比证明全局变量容易得多。
最后,实现良好性能的最佳方法是尽可能完整地向编译器提供有关正在编译的代码的图片。在提供的示例中,可以将func()
添加到同一翻译单元中。然后,如果它不进行其他"未知"调用并且可以内联,则静态分析优化器传递将消除所有不必要的重复读取。对于大型应用程序,LTO(链接时间优化(是提高性能的另一种方法,因为它拓宽了优化程序的视野。
>C++说只有当你将它们标记为这样时,对象才会被volatile
。没有什么是神奇的标记volatile
给你。 您通常可以假设编译器将执行最快的操作,同时仍满足C++规范的要求。因此,只要有帮助,它几乎肯定会缓存访问。
- 在 .h 文件中的类中声明静态变量和在.cpp文件中声明"global"变量有什么区别
- 模板基类中的静态变量
- 类和静态变量
- 不同作用域中的静态变量和全局变量
- 静态变量声明和定义
- 是否可以依赖函数范围的静态变量来执行程序关闭期间调用的方法?
- 在类中继承静态变量?
- "local scope"中的 C++ 初始化静态变量
- 使用静态变量的递归调用的不同输出
- 复制文件流C++静态变量
- 跨模板化函数编译的静态变量
- C++编译器是否优化了顺序静态变量读取?
- C++,每个循环初始化一个新的静态变量
- (为什么)我们可以在初始化中将非静态类成员分配给静态变量吗?
- 这些语句是否等效(静态变量、常量变量和泛型)
- 程序如何知道静态变量是否需要初始化?
- 类外的静态变量实例化
- 无法解析静态变量
- 函数局部静态变量:从性能角度来看的优点/缺点
- 访问从 CPP 文件到其他头文件的静态变量