В python 3.8 shared_memory ресурсный трекер должен быть унаследован подпроцессами, но как это достигается? - PullRequest
1 голос
/ 10 июля 2020

На основе обсуждения в этом отчете об ошибке и соответствующего вопроса SO:

При использовании shared_memory в подпроцессе resource_tracker необходимо унаследовать от родительского процесса. Если это не так, то каждый подпроцесс ошибочно получает свой собственный resource_tracker.

Я не создаю экземпляр resource_tracker нигде в моем коде. Что означает наследование resource_tracker? Как мне создать экземпляр resource_tracker в основном процессе перед созданием новых подпроцессов, чтобы resource_tracker унаследовали подпроцессы?

1 Ответ

2 голосов
/ 21 июля 2020

При использовании shared_memory в подпроцессе, resource_tracker должен быть унаследован от родительского процесса. Если это не так, то каждый подпроцесс ошибочно получает свой собственный resource_tracker.

Этот оператор весьма ошибочен, учитывая текущие реализации как ResourceTracker, так и SharedMemory. Первый реализован как отдельный процесс python, который связывается с процессом, который его запустил (т. Е. Процессом, который создал объект (ы) разделяемой памяти) через канал. У средства отслеживания ресурсов есть конец канала для чтения, а у процесса, создающего объекты общей памяти, - конец для записи. Таким образом, каждый раз, когда начальный процесс создает объект SharedMemory, он отправляет через канал сообщение в трекер ресурсов на register созданный ресурс. Точно так же, если ресурс необходимо удалить, начальный процесс снова будет использовать канал для отправки сообщения unregister. В результате единственный способ, которым дочерний процесс мог по-настоящему наследовать средство отслеживания ресурсов своего родителя, - это отправлять сообщения непосредственно в средство отслеживания ресурсов, используя конец канала для записи (к которому он должен иметь доступ). Однако, поскольку текущая реализация SharedMemory создает трекер ресурсов, даже когда процесс использует только уже созданный объект общей памяти, вашим дочерним процессам придется взаимодействовать с двумя отдельными трекерами ресурсов: одним, запущенным их родителем (через тот же канал), и тот, который запускается, когда они создают экземпляр объекта SharedMemory в первый раз. Разобравшись с этим, давайте займемся вашими вопросами:

Я не создаю экземпляр resource_tracker нигде в моем коде. Что означает наследование resource_tracker?

Во-первых, вы не создаете экземпляр средства отслеживания ресурсов; one создается для вас, когда вы создаете экземпляр объекта SharedMemory в первый раз. И в настоящее время не имеет значения, производите ли вы объект общей памяти или нет. Счетчик ресурсов всегда создается для процесса, создавшего экземпляры объектов общей памяти.

Во-вторых, в текущей реализации на самом деле не предусмотрено наследование трекера ресурсов. Опять же, потребляющие процессы не должны беспокоиться о жизненном цикле объектов общей памяти. Все, о чем им нужно беспокоиться, - это убедиться, что объект действительно существует. Они могут сделать это, обработав исключение FileNotFoundError или OSError. Если текущая реализация SharedMemory не содержит ошибок, когда процессы потребления выполняются с ресурсом, все, что им нужно сделать, это вызвать SharedMemory.close и перейти к чему-то другому.

Как мне сделать создать экземпляр resource_tracker в основном процессе до создания новых подпроцессов, чтобы resource_tracker унаследовал подпроцессы?

Я думаю, проблема в том, что ваш дизайн перевернут. Ваш основной процесс должен создать объект общей памяти и позволить дочерним процессам потреблять его. Идея использования объектов общей памяти заключается в том, чтобы вы могли иметь несколько отдельных процессов, использующих одни и те же блоки памяти, что, в свою очередь, должно ограничивать количество ресурсов, используемых вашей параллельной программой. Но код в связанном сообщении SO делает обратное. Поскольку объекты разделяемой памяти являются постоянными ресурсами ядра, имеет смысл иметь их как можно меньше. Итак, если вы используете дизайн «один производитель, несколько потребителей», вы можете заставить свой основной процесс создать объект общей памяти вместе с соответствующим ему трекером ресурсов, а затем позволить дочерним процессам использовать память. В этом сценарии вы можете выполнить некоторую работу в дочерних процессах, не беспокоясь о связанных с ними трекерах ресурсов. Но просто убедитесь, что дочерние процессы не отсоединяют объект общей памяти до того, как это сделает родительский процесс. Еще лучше, если будет реализовано исправление в отчете об ошибке , сделав ненужным использование процессов для создания трекеров ресурсов, вы можете быть уверены в том, что ваш основной процесс будет единственным объектом, отключающим объект общей памяти.

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

...