为什么 G++ 编译器使用这么多内存

why g++ compiler use so much memory?

本文关键字:内存 G++ 编译器 为什么      更新时间:2023-10-16

我在ubuntu服务器中编写了一个最简单的c ++程序:

测试.cpp:

#include<iostream>
using namespace std;
int a[100*100*100*100*10];
int main() {
    unsigned int count = 0;
    for (int i = 0; i < 100*100*100*100*10; i++) {
        if (i % 10000000 == 0) cout << i << endl; 
        a[i] = i;
        count += i; 
    }
    cout << count << endl;
}

我的 G++ 编译器是:

root@ubuntu:~# g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.6/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.6.3-1ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.6 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --enable-objc-gc --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) 

我的服务器的内存是64GB。当我运行g++ test.cpp时,编译这个C ++文件大约需要1分钟。而 G++ 进步的峰值使用量是 5GB 内存。

为什么?

顺便说一句,当我运行这个程序时,它大约需要 1 分钟才能完成。我想可能是我的记忆有问题。是因为内存太大吗?

关于编译器内存使用的第一个问题是 gcc/g++ 中的一个错误。这个问题以前有人提出过,但现在似乎找不到了。我发现这暗示了同一个问题,但我清楚地记得更直接地提到了这个错误。

无论如何,简而言之,问题如下。首先,假设您的数组已初始化:

int a[100*100*100*100*10] = {10, 20};

这意味着现在整个数组实际上应该写在可执行文件中(所以也应该首先驻留在 g++ 的内存中)。 这很慢,因为a真的很大(4GB)。现在,如果数组没有初始化,就像您的情况一样,它应该转到.bss部分,并且在您运行它时分配/初始化整个数组。这意味着不需要将其写入文件。

这也意味着 g++ 可以跳过将整个数组放在内存中。这就是错误出现的地方。G++ 确实将该数组保存在内存中,只是后来才决定不写入它。此错误稍后会得到修复,您可以在另一个答案的报告中看到。


执行时间长的第二个问题是很自然的。你正在做十亿次的事情。做十亿次的事情需要时间!

一个好的经验法则是"一个由 1000 万次轻量级计算组成的循环需要一秒"。因此,您可以想象 100 次操作的 100 次乘以大约 100 秒(即一分钟的数量级)。

我没有问题 - 它工作正常。

我本以为是因为它试图弄清楚是否展开循环,但由于您不使用任何优化标志......

旁注:你不应该编译 can 作为 root。

Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.8.1-10ubuntu8' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.1 (Ubuntu/Linaro 4.8.1-10ubuntu8)