2013-11-07 5 views
0

Я написал простую программу на C++ в моей Ubuntu сервера:Почему g ++ компилятор использует столько памяти?

test.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; 
} 

и мой г ++ компилятор является:

[email protected]:~# 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 ++-прогресса составляет 5 ГБ памяти ....

Почему?

Кстати, когда я запускаю эту программу, ей нужно около 1 минуты, чтобы закончить. Я думаю, может быть, что-то не так с моей памятью. Это потому, что память слишком велика?

+0

В качестве стороннего варианта я могу предложить 'const int BufferSize = 100 * 100 * 100 * 100 * 10;' вместо того, чтобы использовать тот же магический номер дважды – Sean

+0

Я подозреваю, что stackoverflow.com не подходит для этого вопроса спросил, однако ... если вы измените размер своей константы, вы, скорее всего, увидите отличную производительность от компилятора.Вы не упомянули, какие флаги компилятора вы используете, но если выполняется какая-либо оптимизация, эта константа может быть огромной проблемой в качестве контрольной точки цикла (в то время как компилятор решает, должен ли он развернуть цикл). – mah

+0

Компиляция заняла всего 2 секунды на виртуальной машине с 2 ГБ оперативной памяти. Конечно, я не могу запустить программу там, но если вам действительно нужна 1 минута, чтобы скомпилировать эту программу, я бы сказал, что есть что-то очень ужасное. Можете ли вы запустить быстрый hd perftest ('hdparm -t/dev/yourhd'), чтобы узнать, связано ли это с памятью или диском? И проверьте dmesg, возможно, ваш диск умирает от вас. – fvu

ответ

7

Первая проблема использования памяти компилятором - ошибка в gcc/g ++. Этот вопрос был поднят раньше, но я не могу сейчас его найти. Я нашел this, намекая на ту же проблему, но я отчетливо помню более прямое упоминание об этой ошибке.

В любом случае, одним словом, проблема в следующем. Во-первых, предположим, что ваш массив инициализируется:

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

Это означает, что теперь весь массив должен быть на самом деле написано в исполняемый файл (так же должны постоянно находиться в первых г ++ с памятью). Это медленно, потому что a действительно большой (4 ГБ). Теперь, если массив не был инициализирован, как и в вашем случае, он должен перейти в раздел .bss, и весь массив будет выделен/инициализирован только при его запуске. Это означает, что его не нужно записывать в файл.

Это также означает, что g ++ может пропускать весь массив в памяти. Здесь возникает ошибка. G ++ делает хранить этот массив в памяти и только позже решает не записывать его. Эта ошибка позже исправлена, как вы можете видеть в отчетах в another answer.


Вторая проблема с исполнением длительной является естественной. Вы делаете что-то миллиард раз. Выполнение чего-то миллиарда раз требует времени!

Хорошее эмпирическое правило: «цикл из 10 миллионов легких вычислений берет в порядке секунды». Таким образом, вы можете себе представить, что 100 раз 10 миллионов операций занимали бы около 100 секунд (т. Е. В порядке минуты).

+0

Третий вопрос: обычно вы прибегаете к распределению динамической памяти для чего-либо, что является большим (и 3.7 ГБ, безусловно, большой). –

+0

@MatteoItalia, что _is_ то, что вы обычно делаете да. Но это не связано с тем, почему усложнение и исполнение занимают такое долгое время. В противном случае есть много проблем с самим кодом. Например, 'count' является неподписанным при добавлении с подписанными числами, кроме того, что он достаточно мал, чтобы очень легко переполнить при суммировании одного миллиарда чисел. – Shahbaz

+0

Конечно, но я хотел бы указать на это, поскольку для меня это самая очевидная проблема с этим кодом; сам факт, что такая ошибка проскальзывала в 'g ++', исходит из того, что в любом случае вы не должны иметь таких больших глобальных массивов. –

1

У меня нет проблем с ней - она ​​работает нормально.

Я бы предположил, что это потому, что он пытается выяснить, является ли раскатать цикл или нет, но так как вы не используете какие-либо флаги оптимизации ...

Side Примечание: Вы не должны компилировать могли в корне.

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) 
Смежные вопросы