2014-09-25 2 views
4

Я работаю над университетским исследовательским проектом на C++ с много шаблонов, у которых есть дополнительные вложенные шаблоны и так далее. Проект касается эффективных структур данных индекса для конкретной области исследований. Вы можете себе представить: структура индекса имеет множество параметров для настройки, поэтому мы используем параметры шаблона чрезмерно. Конечно, мы хотим протестировать наши индексы с разными наборами параметров, поэтому существует множество экземпляров шаблонов.Как сделать ссылку на C++ меньше памяти

Проект не такой огромный. Возможно 50k LOC. Но все же, связь занимает 50 секунд и потребляет более 7 ГБ памяти (!!!). Я на 32-Гбайт рабочей станции, поэтому все в порядке для меня. У меня часто есть бакалавр и магистранты, работающие над этим проектом. Проблема в том, что они часто работают на ноутбуках с 4 или 8 ГБ оперативной памяти. Таким образом, у этих студентов большие проблемы, связанные с этим проектом. Получающаяся тестовая двоичная (т. Е. Двоичная, которая просто содержит единичные тесты для структур индекса) составляет 700 мегабайт. Большинство из них являются символами, потому что вложенные шаблоны создают огромные имена. Если я использую strip в двоичном формате, он падает до 8 мегабайт.

Так есть способ уменьшить использование ОЗУ во время связи? И есть ли способ иметь меньшие символы даже с вложенными шаблонами?

Скомпилировать, используя g ++ 4.9 с std=c++11 под Ubuntu 14.10.

Edit:

Это действительно кажется, вложенные шаблоны. У нас есть два тестовых примера с действительно глубоко вложенными шаблонами. Два файла .o для этих тестов составляют почти 90% памяти окончательного двоичного файла. Они приводят к именам методов, длина которых превышает 3000 символов. Здесь нет способа не использовать вложенные шаблоны, поскольку они образуют «дерево обработки» примерного запроса. Есть ли способ сохранить короткие имена при использовании глубоко вложенных шаблонов?

+1

Что OS, компилятор версия? – EdChum

+0

@EdChum: g ++ 4.9 под Ubuntu 14.10. Добавил его к вопросу сейчас. – gexicide

+0

Какая версия на C++? C++ 11 имеет внешние шаблоны! –

ответ

2

GCC имеет схему сбора мусора для используемой оперативной памяти.

Параметры ggc-min-expand и ggc-min-heapsize используются, чтобы определить, когда GCC должен очистить и удалить его неиспользованную память (их значения по умолчанию - это процентная доля от общей системной памяти).

Вы могли бы попробовать что-то вроде:

g++ --param ggc-min-expand=0 --param ggc-min-heapsize=8192 

От руководства GCC:

GGC-мин-расширения

GCC использует сборщик мусора для управления своим собственным распределением памяти , Этот параметр указывает минимальный процент, с помощью которого куба коллектора должна быть расширена между коллекциями. Настройка может улучшить скорость компиляции; он не влияет на генерацию кода .

По умолчанию 30% + 70% * (ОЗУ/1 ГБ) с верхней границей 100% при ОЗУ> = 1 ГБ. Если доступно getrlimit, понятие «ОЗУ» - это наименьшее из фактических ОЗУ, RLIMIT_RSS, RLIMIT_DATA и RLIMIT_AS. Если GCC не может вычислить ОЗУ на конкретной платформе, используется нижняя граница из 30%. Установка этого параметра и ggc-min-heapsize в ноль заставляет производить полную сборку при каждой возможности. Это чрезвычайно медленный, но может быть полезен для отладки.

GGC-мин-heapsize

Минимальный размер кучи сборщика мусора, прежде чем он начинает потрудившись сбора мусора. Первая коллекция возникает после того, как куча расширяется на ggc-min-expand% за пределами ggc-min-heapsize. Опять же, настройка может улучшить скорость компиляции и не влияет на генерацию кода . По умолчанию используется RAM/8, нижняя граница 4096 (четыре мегабайта) и верхняя граница 131072 (128 мегабайт). Если getrlimit имеет значение , понятие «ОЗУ» является наименьшей из фактической ОЗУ, RLIMIT_RSS, RLIMIT_DATA и RLIMIT_AS. Если GCC не может вычислить ОЗУ на конкретной платформе, используется нижняя граница. Установка этого параметра очень велика, что эффективно отключает сбор мусора. Установка Этот параметр и ggc-min-expand до нуля приводит к тому, что полная коллекция возникает при каждой возможности.

Дальнейшие детали:

+0

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

+0

Вы правы, есть компромисс между временем связывания и потреблением памяти. Более того, «оптимальные» значения могут меняться. – manlio

3

Так есть ли способ, чтобы уменьшить использование оперативной памяти во время связи? И есть ли способ иметь меньшие символы даже с вложенными шаблонами?

Рассматривали ли вы с помощью Pimpl идиомы в коде клиента?

Рассмотрим ситуацию, когда у вас есть это включает цепь:

Ах -> Bh -> Ch -> Dh (C включает D, B включает в C, и т.д.)

Пусть А определяет класс АА, Bh определяет класс B и т. Д. (С AA реализуется в терминах BB, BB реализуется в терминах CC и т. Д.).

Если DD большой шаблон и используется в реализации CC, то шаблонный код будет скомпилирован в три раза, для компиляции блоков A, B и C.

Теперь рассмотрим, что произойдет, если вместо Ch в том числе Dh, у вас есть следующая ситуация:

Ch foward объявляет CCImpl *pimpl и пересылает все его методы в pImpl-> методов (и не включает Dh).

C.cpp содержит C.h и D.h и реализует CCImpl и CC.

Теперь D будет включен после (и скомпилирован один раз, для C.cpp). A и B будут включать только C.h, с объявлением вперед CImpl. A.h, B.h и C.h больше не знают, что шаблон существует.

+0

Я это рассмотрел, спасибо. Проблема заключается в том, что наш университетский проект посвящен измерению производительности очень эффективных высокопроизводительных структур данных очень низкого уровня. Таким образом, мы даже не можем заплатить цену за дополнительное разделение (и неудачные возможности вложения, которые приходят с ним). Иногда нам приходится даже рассчитывать средние циклы и иметь всего лишь десять циклов на операцию. – gexicide

1

Использовать наследование разумно. У вас может быть class Foo<1,4,8,1,9,int, std::string> в качестве базового класса для class Bar, а затем в объектном файле указывается только Bar.

Отметьте, что typedef не содержит имен для ссылок.

[править] И для решения производительности беспокойства от другого комментария, пустой производный класс не добавляет накладные расходов на общих компиляторах при нормальных уровнях оптимизации (и часто нет никаких накладных расходов даже в отладочной версии)

Смежные вопросы