0

我在我的 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 分钟才能完成。我想可能是我的记忆有问题。是不是内存太大了?</p>

4

2 回答 2

7

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

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

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

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

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


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

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

于 2013-11-07T14:52:37.800 回答
1

我对此没有任何问题 - 它工作正常。

我猜这是因为它试图弄清楚是否展开循环,但因为你没有使用任何优化标志......</p>

旁注:您不应该以 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) 
于 2013-11-07T14:47:45.070 回答