当这个变量通过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;
}
如果编译器能够毫无疑问地证明该值在不同的访问之间不会发生变化,那么根据? 如果规则 它可能会将多个读合并为一个。
但是,证明一个具有静态存储持续时间的变量往往很难做到,因为在其他翻译单元中可能存在代码(func()
在你的例子中),修改了它。所以在没有看到 func()
的时候,编译器会被迫重新加载 data
在每次迭代中。同样,当 func()
本身是编译的,它的参数每次都需要重新加载。
那么也可能有其他 线程 修改 data
. 根据C++的规定 记忆模型 规则,这些变化在同步事件发生之前是不可见的,同步事件可以是内存栅栏、mutex或原子acquirerelease等。
所以,是的,减少一个变量的范围可能经常会带来性能的提高。要证明一个局部变量不能从 "外部 "修改,要比一个全局变量容易得多。
最后,实现良好性能的最好方法是让编译器尽可能完整地了解正在编译的代码。在提供的例子中。func()
可以添加到同一个翻译单元中。然后,如果如果它没有进行其他 "未知 "的调用,并且可以内联,静态分析优化器通过将消除所有不必要的重复读取。对于大型应用,LTO(Link Time Optimization)是另一种提高性能的方法,因为它为优化器拓宽了视野。
C++说对象只 volatile
如果你把它们标记成这样。没有任何东西被神奇地标记为 volatile
为你所用。 你通常可以认为编译器在满足C++规范要求的同时,会做任何最快的事情。所以它几乎肯定会缓存访问,只要有帮助。