gpt4 book ai didi

c++ - 优化非成本变量访问

转载 作者:太空狗 更新时间:2023-10-29 21:44:31 27 4
gpt4 key购买 nike

我面临一个有趣的优化问题。

在由大量类组成的大型代码库中,在许多地方经常使用/检查非常量全局(=文件范围)变量的值,并且该变量的不必要的内存访问是避免。

这个变量只初始化了一次,但是由于初始化比较复杂,需要调用很多函数,所以不能这样初始化,在执行main()之前:

unsigned size = 1000;

int main()
{
// some code
}

unsigned size = CalculateSize();

int main()
{
// some code
}

相反,它必须像这样初始化:

unsigned size;

int main()
{
// some code
size = CalculateSize();
// lots of code (statically/dynamically created class objects, whatnot)
// that makes use of "size"
return 0;
}

仅仅因为 size 不是常量,它是全局的(=文件范围)并且代码又大又复杂,编译器无法推断出 sizesize = CalculateSize(); 之后永远不会改变。编译器生成的代码从变量中获取和重新获取 size 的值,并且不能将其“缓存”在寄存器或可能位于 CPU 的本地(堆栈)变量中d-cache 以及其他经常访问的局部变量。

因此,如果我有类似以下内容(出于说明目的而编造的示例):

  size = CalculateSize();
if (size > 200) blah1();
blah2();
if (size > 200) blah3();

编译器认为 blah1()blah2() 可能会改变 size 并生成从 size< 读取的内存if (size > 200) blah3(); 中。

我想随时随地避免额外阅读。

显然,黑客攻击是这样的:

const unsigned size = 0;

int main()
{
// some code
*(unsigned*)&size = CalculateSize();
// lots more code
}

不会执行,因为它们会调用未定义的行为。

问题是一旦执行了size = CalculateSize();,如何通知编译器它可以“缓存”size 的值,并且无需调用未定义的行为未指定的行为,希望是特定于实现的行为

这是 C++03g++ (4.x.x) 所必需的。 C++11 可能是也可能不是一个选项,我不确定,我试图避免使用高级/现代 C++ 功能以保持在编码指南和预定义工具集中。

到目前为止,我只是想出了一个技巧,在每个使用它的类中创建 size 的常量拷贝并使用拷贝,就像这样 (decltype 使其成为 C++11,但我们可以不用 decltype):

#include <iostream>

using namespace std;

volatile unsigned initValue = 255;
unsigned size;

#define CACHE_VAL(name) \
const struct CachedVal ## name \
{ \
CachedVal ## name() { this->val = ::name; } \
decltype(::name) val; \
} _CachedVal ## name;

#define CACHED(name) \
_CachedVal ## name . val

class C
{
public:
C() { cout << CACHED(size) << endl; }
CACHE_VAL(size);
};

int main()
{
size = initValue;
C c;
return 0;
}

以上内容可能只在一定程度上有所帮助。是否有更好的、对编译器更有启发性的合法 C++ 替代方案?希望有一个最小侵入性(源代码方面)的解决方案。

更新:为了更清楚一点,这是在对性能敏感的应用程序中。这并不是说我一时兴起要摆脱对该特定变量的不必要读取。我试图让/使编译器产生更优化的代码。涉及以 size 的频率读取/写入另一个变量的任何解决方案以及以 size 的频率执行的解决方案中的任何其他代码(尤其是分支和条件分支)被称为也会影响性能。我不想在一个地方赢了,却在另一个地方输了同样甚至更多。

这是一个相关的non-solution, causing UB (至少在 C 中)。

最佳答案

C++ 中有 register 关键字,它告诉编译器您计划大量使用一个变量。不知道您正在使用的编译器,但大多数现代编译器都会为用户执行此操作,并在需要时将变量添加到注册表中。您还可以将变量声明为常量并使用 const_cast 对其进行初始化。

关于c++ - 优化非成本变量访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19884871/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com