Назад | Перейти на главную страницу

Автоматически приостанавливать / переводить процесс в спящий режим, когда используется слишком много памяти

Я запускаю небольшой вычислительный кластер Debian на 8-ядерном ПК с 16 ГБ ОЗУ. Я выполняю пакеты из примерно 1 тыс. Задач (у каждого пакета есть общее ожидаемое время завершения в месяц). Одна задача является однопоточной (поэтому я могу запускать несколько из них параллельно на каждом ПК), не требует большого количества операций ввода-вывода (загружает несколько мегабайт данных при запуске и сбрасывает несколько мегабайт данных при выходе; не взаимодействует с внешним миром в противном случае), время его работы неизвестно (от нескольких минут до ~ недели), потребление памяти неизвестно (от нескольких мегабайт до ~ 8 ГБ; использование может расти медленно или быстро). Я хотел бы выполнять как можно больше таких задач параллельно на одном ПК, но я хочу избежать чрезмерной подкачки.

Так что у меня появилась идея: я мог бы отслеживать использование памяти этими задачами и приостанавливать (kill -SIGSTOP) или в спящий режим (используя такой инструмент, как CryoPID) задачи, которые потребляют слишком много памяти, чтобы перезапустить их позже. Под использованием памяти я имею в виду количество «активных виртуальных страниц» или количество выделенных, а не совместно используемых страниц памяти, которые фактически были затронуты (эти задачи могут выделять память, не используя их).

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

Я мог бы использовать настоящие виртуальные машины, но в этом случае они, похоже, имеют значительные накладные расходы - отдельное ядро, выделение памяти и т. Д. Уменьшили бы доступную память; Мне пришлось бы запустить 8 из них. Кроме того, насколько я знаю, они добавили бы дополнительные вычислительные ресурсы.

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

Есть ли другие варианты?

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

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

Что касается остановки процесса, когда он достигает определенного уровня использования памяти, я могу придумать хак, который сделает это.

  • Вы создаете контрольную группу, которая содержит подсистемы замораживания и памяти.
  • Поместите свою задачу (и) в cgroup.
  • Присоединить процесс к cgroup.event_control и установите порог памяти, который вы не хотите превышать (это несколько объясняется в документация ядра.)
  • По истечении времени вы замораживаете контрольную группу. Ядро должно в конечном итоге исключить эти страницы для обмена (при условии, что в вашей контрольной группе их достаточно).

Обратите внимание, что контрольная группа «заморозить» не будет вытеснять страницы в постоянное местоположение носителя, но она заменит страницы, когда пройдет достаточно времени и страницы понадобятся для чего-то еще.

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

  • Откуда вы знаете, что было бы лучше позволить процессу, использующему большой объем памяти, просто работать быстрее, чтобы быстро завершить интенсивный период памяти и освободить память?
  • Если вы попытаетесь правильно разбудить процессы с помощью циклического перебора процессов - вы можете возразить, что выполняете работу хуже, чем то, что планировщик ЦП уже делает за вас.
  • Если некоторые процессы более важны, чем другие (и их следует разбудить дольше / закончить быстрее), вероятно, лучше просто выделить им больше времени процессора, чем полностью замораживать другие процессы.
  • Хотя это будет медленно - вы можете добавить много свопа (чтобы никогда не перегрузить), а затем значительно уменьшить интерактивность планировщика, чтобы попытаться помочь вам уменьшить агрессивное вытеснение страниц. Это делается в sched_min_granularity_ns.

К сожалению, лучшим решением будет возможность чекпоинта ваших задач. Жалко, что большинство реализаций еще недостаточно конкретны.

В качестве альтернативы, вы можете подождать пару лет, пока в ядре не появится надлежащая контрольная точка / восстановление!

Я предполагаю, что этот вопрос немного преувеличивает, или я его неправильно понял, но вы ищете что-то вроде

ps auxww, а затем проверьте столбец VSZ. Затем, если VSZ достигает определенной суммы, вы выполняете свой SIG по этому процессу? А потом просто запускать команду через свой любимый интервал?

Со страницы руководства ps

vsz Размер виртуальной памяти VSZ процесса в КиБ (1024-байтовые блоки). Сопоставления устройств в настоящее время исключены; это может быть изменено. (псевдоним vsize).