Программа на С ++ показывает очень разное поведение памяти на разных машинах

0

Я написал компьютерное моделирование в C++, которое требует большой памяти. Он работает в итерациях, и на каждой итерации выделяется большой объем памяти, который должен быть освобожден в конце итерации. Он также использует C++ 11 реализацию <thread> для параллельной работы.

Когда я тестирую программу на своем настольном компьютере, она работает отлично: она никогда не превышает память, которую я ей разрешаю, а во время итераций ничего не складывается. Однако, когда я отправляю программу в наш вычислительный кластер, используемая память (к которой у меня есть доступ только через программное обеспечение для очередей) растет со временем и намного превышает память, используемую на моей машине.

Позвольте мне вначале показать вам очень грубо, как структурировано программное обеспечение:

for thread in n_threads:
    vector<Object> container;
    for iteration in simulation:
        container.clear()
        container.resize(a_large_number)
        ... do stuff ...

Скажем, на моей машине контейнер съедает 2GB памяти. Я вижу как в htop и в valgrind --tool=massif что эти 2GB никогда не превышают. Ничто не складывается. Тем не менее, в кластере я вижу, как память растет и растет, пока она не станет намного больше, чем 2GB (и рабочие места будут убиты/узел вычислений зависает...). Обратите внимание, что я ограничиваю количество потоков на обеих машинах и могу быть уверенным, что они равны.

Я знаю, что libc в кластере очень старый. Чтобы скомпилировать мою программу, мне нужно было скомпилировать новую версию g++ и обновить libc на переднем узле кластера. Программное обеспечение отлично работает на вычислительных узлах (за исключением этой проблемы с памятью), но libc там намного старше. Может ли это быть проблемой, особенно вместе с потоками, для распределения памяти? Как я могу это расследовать?

Теги:
multithreading
c++11
memory
libc

1 ответ

1

Да, в зависимости от того, сколько лет GNU libc, возможно, вам не хватает некоторых важных оптимизаций выделения памяти. Вот некоторые вещи, которые нужно попробовать (разумеется, рискуя штрафами за производительность):

  1. Вы можете попробовать настроить malloc/free поведение через mallopt(); используйте M_MMAP_MAX и M_MMAP_THRESHOLD, чтобы поощрять больше распределений проходить через mmap(), таким образом, память, как гарантируется, будет возвращена системе после free().

  2. Попробуйте сделать ваш контейнер-распределитель __gnu_cxx::malloc_allocator, чтобы убедиться, что mallopt() влияют на контейнер.

  3. Попробуйте вызвать container.shrink_to_fit() после изменения размера, чтобы убедиться, что вектор не удерживает больше памяти, чем это необходимо.

  • 0
    Привет, спасибо за комментарий. Я попробовал третий вариант, но это не помогло. Кажется, что во взаимодействии между моим кодом и libpthread кластера (или libc в целом) есть какая-то фундаментальная ошибка. Если я ограничу все одним потоком, т. Е. Основным потоком, он будет нормально работать на всех машинах. Я сдался, поскольку операционная система кластера слишком старая, чтобы можно было легко компилировать более новую версию libc. Однопоточный это.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню