Утечка памяти в C ++ OpenMP-коде

Я написал код openmp на C ++, в котором есть динамическая выделенная память в параллельной области, область находится в цикле while. Динамически выделяемая память освобождается в конце параллельной области в каждом цикле. Я слежу за памятью через / proc / self / stat на машине linux после каждого выделения и освобождения. Я нахожу немного меньше памяти в размере резидентного набора. Почему это так ? Код что-то вроде —

float *dynm;
while(condition)
{
pragma omp parallel shared(list of variables) private(dynm)
{
read_values_from_/proc/self/stat_print_rss;
dynm = new float[size];
read_values_from_/proc/self/stat_print_rss;
pragma omp for schedule(static, chunk) nowait
for(counter)
{
do_operation;
}
delete []dynm;
read_values_from_/proc/self/stat_print_rss;
}
}

3

Решение

Измерение RSS не очень точный способ поиска утечек памяти из-за очень сложного способа его вычисления. Существуют специальные отладчики памяти, такие как valgrind или тот, который встроен в glibc это может сказать вам, если память протекает. Вы также должны понимать, что glibc использует два совершенно разных механизма для динамического выделения памяти.

Для больших распределений он выполняет частные анонимные карты памяти, используя mmap(2) системный вызов. Этот метод может выделять только блоки с размерами, кратными размеру системной страницы (4 КиБ в большинстве современных архитектур), поэтому он не подходит для небольших распределений. Это даже не подходит для больших выделений, когда слишком много памяти будет потрачено впустую, например если вы хотите выделить блок из 17 КиБ, то нужно выделить 20 КиБ (5 раз по 4 КиБ) и 15% памяти будет потрачено впустую.

Для меньших распределений используется предоставляемая системой куча. Есть что-то под названием разрыв системы, где заканчивается сегмент данных процесса. Это может быть перемещено с brk(2) Системный вызов, чтобы выделить больше памяти и вниз, чтобы освободить ее. Поскольку для каждого процесса существует только одна область кучи, а ОС рассматривает ее как один блок, в нее встроен специальный менеджер кучи. glibc это может далее подразделить этот блок на меньшие распределения.

C ++ new звонки оператора malloc(3) от glibc выполнить выделение памяти. malloc(3) вызовы одного из двух механизмов выделения памяти, описанных выше, в зависимости от размера выделяемого блока памяти. C ++ delete звонки оператора free(3) от glibc который является аналогом освобождения malloc(3), То, что происходит после освобождения блока памяти, во многом зависит от того, как он был выделен в первую очередь.

Память, которая была выделена с помощью mmap(2) механизм освобождается путем его отображения munmap(2), Это удаляет отображение памяти из виртуального адресного пространства процесса и освобождает страницы физической памяти, которые использовались для выделения ресурсов.

Все гораздо сложнее для памяти, которая была выделена в куче, и в большей степени зависит от алгоритма, который используется для ее управления. Если освобождаемый блок находится не в конце кучи, а скорее где-то еще, размер кучи не может быть уменьшен, так как существуют другие выделения в верхних адресах памяти. Это только одна из многих форм, в которых так называемые фрагментация кучи проявляет себя. Другая возможная причина, по которой не наблюдается уменьшение используемой памяти, заключается в том, что менеджер кучи может принять решение не возвращаться назад к позиции разрыва в ожидании возможных будущих распределений и вызова brk(2) это дорогая операция.

5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]