Конфликт блокировки при распределении памяти - многопоточный или многопроцессорный

Мы разработали большое приложение C++, которое удовлетворительно работает на нескольких сайтах на больших компьютерах Linux и Solaris (до 160 процессорных ядер или даже больше). Это многопоточная (более 1000 потоков), однопроцессная архитектура, потребляющая огромные объемы памяти (более 200 ГБ). Мы LD_PRELOADing используем Google Perftool tcmalloc (или libumem/mtmalloc в Solaris), чтобы избежать узких мест в производительности при выделении памяти и в целом хороших результатов. Тем не менее, мы начинаем видеть неблагоприятные последствия конфликта блокировок во время выделения / освобождения памяти на некоторых более крупных установках, особенно после того, как процесс запущен какое-то время (что намекает на эффекты устаревания / фрагментации распределителя).

Мы рассматриваем возможность перехода на многопроцессорную / разделяемую архитектуру памяти (интенсивное распределение / освобождение не будет происходить в разделяемой памяти, а в обычной куче).

Итак, наконец, вот наш вопрос: можем ли мы предположить, что менеджер виртуальной памяти современных ядер Linux способен эффективно передавать память сотням параллельных процессов? Или мы должны ожидать, что столкнемся с теми же проблемами с распределением памяти, которые мы наблюдаем в нашей среде с одним процессом или многопоточностью? Я склонен надеяться на улучшение общей производительности системы, поскольку мы больше не будем ограничиваться одним адресным пространством, а наличие нескольких независимых адресных пространств потребует меньшего количества блокировок со стороны диспетчера виртуальной памяти. У кого-нибудь есть фактический опыт или данные о производительности, сравнивающие многопоточное и многопроцессорное распределение памяти?

1 ответ

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

Нет причин ожидать этого. Если ваш код не настолько плохо спроектирован, что он постоянно возвращается к ОС для выделения памяти, это не будет иметь существенного значения. Ваше приложение должно возвращаться к диспетчеру виртуальной памяти операционной системы только тогда, когда ему нужно больше виртуальной памяти, что не должно происходить значительно, когда процесс достигает своего стабильного размера.

Если вы постоянно выделяете и освобождаете весь путь назад к ОС, вам следует прекратить это делать. Если нет, то вы можете хранить несколько пулов уже выделенной памяти, которые могут использоваться несколькими потоками без конфликтов. И, как преимущество, ваши контекстные переключатели будут дешевле, потому что TLB не нужно очищать.

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

Другие вопросы по тегам