【发布时间】:2013-10-04 08:06:47
【问题描述】:
今天在编译我的程序时,我注意到 GCC 的内存消耗模式(编译步骤)中有一些非常奇怪的东西(我确信可以以某种方式解释)。名为“cc1plus”的进程正在使用大约 10 GB 的 RAM 来运行少于 10 000 行代码的程序。在注释和取消注释代码行之后,我终于找到了“罪魁祸首”:
std::bitset<UINT_MAX>
如果你想测试自己,请试试这个非常简短的程序:
#include <iostream>
#include <bitset>
#include <climits>
std::bitset<UINT_MAX> justAVar;
int main()
{
std::cout << UINT_MAX << std::endl;
return 0;
}
使用 -std=c++11 或 -std=c++0x 编译它 请注意,即使是这个小例子编译时也会使用大量 RAM(在我的情况下,gcc 的两个盒子都是 7 GB,clang 是 2.6)所以如果你必须按下重置按钮,不要像没有被警告过一样抱怨和诅咒神。
我的测试机器:
设置 1:Debian 7.0 64,gcc 4.8.1
设置2:Ubuntu 12.04 64、gcc 4.7.3、gcc 4.8.1、clang 3.0.6(最后一个使用-std=c++0x)
一个关于 bitset 构造函数实现的提示(显然,由 if def 为 C++11 和 C++0x 保护),正如我的一位好心同事向我展示的那样:它是使用 constexpr 声明的em>
现在的问题是:有人可以向我(我们)解释一下在这种情况下使用所有这些编译器会发生什么吗?
谢谢
【问题讨论】:
-
您正在静态分配一个巨大的位集,要求编译器为其运行构造函数。我知道我没有提供很多关于为什么会发生这种情况的情报,但是您是否尝试过将一些详细的输出标志传递给编译器?
-
@cyphar 500MB 不是“他妈的巨大”。对于现代机器和软件来说,这是一个合理的内存量。
-
500MB 实在是太大了。这是一个非常大的结构。使用这种大小的结构,您可以真正存储 Linux CD 映像的位图。此外,导致它占用如此多内存的原因是优化 500MB 结构的难度。作为比较,我当前运行的 *kernel 使用了 85 MB 内存。这比 OP 程序中的一种结构小不到 5 倍。
-
@cyphar 正如丹尼尔所说,UINT 现在并不庞大,其次,我发布了这个问题,以了解 gcc 试图做出的“神奇”优化是什么,我需要社区的帮助那
-
@asalic 这不是关于特定的“神奇”优化,我认为这是关于跟踪状态作为优化的基础,甚至可能是强制
constexpr在某些情况下是因为编译器必须知道constexpr的值。