int **something = new int *[N];
for(int n = 0; n < N; n++)
something[n] = new int[M];
#pragma omp parallel for
for (int n = 0; n < N; n++)
delete[] something[n];
delete[] something;
Могу ли я распараллелить процесс удаления таким образом?
Убийца OOM Linux убил мой процесс после довольно большого количества циклов. Я пытался выяснить, где происходит утечка памяти, но не нашел, где. Я не уверен, хорошо ли работал этот процесс удаления цикла for или нет.
Ваша куча свободна от блокировки? Было бы иронично, если бы в куче был мьютекс, который бы сериализовал операции.
Стыдно признаться, что потребовалось всего 20 лет, чтобы осознать шутку, лежащую в основе имени командира боевых дроидов OOM-9.
Убийца OOM Linux убил мой процесс после довольно большого количества циклов. Как в этом поможет распараллеливание delete
вызовов?
Возможно, вам нужно изучить использование виртуальной памяти и увеличить размер свопа.
Извините за мой плохой запутанный вопрос. Я только что зарегистрировался на stack overflow и начал программировать всего месяц назад. Даже не английский пользователь. Я сделал проект, прогнал его на ~100000 циклов, и он был убит. Поэтому я попытался выяснить, где произошла утечка памяти, и у меня возникли сомнения по поводу этой части кода. Я не знал, что распараллеливание освобождения памяти на самом деле не помогает.
Использование new
считается плохим C++. Почему вы не используете стандартные контейнеры, которые гораздо более безопасны для памяти?
Обычно это нормально. Стандартная куча (g)libc должна быть потокобезопасной; в противном случае было бы вообще невозможно писать многопоточные программы. Также можно выделить буфер в одном потоке и освободить его в другом.
Распараллеливание распределения кучи не даст вам большого ускорения, но я подозреваю, что вы спрашиваете не потому, что хотите ускорить (де-)распределение, а скорее потому, что у вас есть какой-то другой параллельный код, который выделяет и освобождает некоторые буферы.
Чтобы найти утечку, попробуйте запустить программу с помощью valgrind.
Кроме того, рассмотрите возможность вызова malloc_trim(0);
после освобождения больших объемов памяти. Это заставляет glibc освобождать неиспользуемую память обратно в операционную систему, вместо того, чтобы удерживать всю ее для последующего выделения.
Распараллеливание выделений на самом деле помогло бы, поскольку разные потоки имеют разные области памяти. Так что это можно распараллелить. Я только что проверил это и обнаружил фактор 4 в своей системе. Простое распараллеливание освобождения не поможет, так как каждый поток будет конкурировать за блокировку с одной ареной, где все было выделено.
@ Homer512 Распараллеливание выделений действительно помогло бы, поскольку разные потоки имеют разные области памяти. Только в том случае, если выделения недостаточно велики, чтобы их можно было заменить на mmap()
или вызвать повторные вызовы [s]brk()
, чтобы получить больше памяти. Любой из них потребует создания и сопоставления новых страниц виртуальных машин, ни одна из которых не может быть многопоточной.
@AndrewHenle Правда, это зависит от размера
Я не ожидал таких быстрых отзывов от многих пользователей, так как я здесь первый. Многому научился и собираюсь попробовать то, что вы упомянули во время отладки.
Но почему? Экономит ли распараллеливание этой операции достаточно времени, чтобы обойти настройку и демонтаж?