C++编译器是否优化了顺序静态变量读取?

Do C++ compilers optimize sequential static variable reading?

本文关键字:静态 变量 读取 顺序 编译器 是否 优化 C++      更新时间:2023-10-16

当通过 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++规范的要求。因此,只要有帮助,它几乎肯定会缓存访问。