Я работаю над сценарием резервного копирования, который использует модуль Python multiprocessing
, чтобы разделить его работу между несколькими дочерними процессами.По большей части это относительно простой процесс.В условиях тестирования некоторое время назад я обнаружил, что могу получить увеличение скорости примерно на 20% по сравнению с однопроцессной обработкой, если я: 1. Разделю файлы, которые будут добавлены в выходной файл (ы), на отдельные задачи и;2. Пусть количество рабочих, равное количеству процессорных ядер машины (в моем случае, 4), делит эту работу между собой.
Я изначально реализовал это в Linux, используя объекты mp.Lock (), которыебыли брошены в словарь, аргументированный дочерним процессам во время выполнения.По понятным причинам это не работает в Windows (из-за ограничения метода создания процесса spawn ()), поэтому с тех пор я попытался:
- Реализация процесса менеджера (кажется, неправильно делиться с детьми)
- Включая объекты mp.Lock () в качестве аргументов задач, а не процессов (не может быть сделано, python принимает блокировки у детей только по наследству)
- Отказаться от примитива блокировки в целом для реализации блокировки файлов на уровне FS / OS с использованием
msvcrt
и fcntl
.
Когда я делаю это с помощью fcnt.lockf (), я могу правильно получить блокировки, но дочерний процесс не может затем записать свой вывод в файл, даже если он думает, что это происходит (как, например, исключение не вызывается).Моя реализация fcntl выглядит следующим образом:
import fcntl
print("Gonna open %s" % self.tarf)
#try:
file = open(self.tarf, "a+b")
file.seek(0)
print("Can I lock?")
fcntl.lockf(file, fcntl.LOCK_SH)
print("got the lock")
tar = tarfile.open(fileobj=file, mode="a:")
print("tarfile opened")
info = tar.gettarinfo(self.b, self.a)
with open(self.b, "rb") as fd:
tar.addfile(info, fd)
print("file inserted: %s" % self.a)
tar.close()
fcntl.lockf(file, fcntl.LOCK_UN)
file.close()
waiting = False
У меня два вопроса:
- Есть ли правильный способ сделать это без использования mp.Lock ()объекты?
- Есть ли особая хитрость в использовании менеджеров в окнах, на которую не распространяется аргумент прокси-объектов менеджера (скажем, dict_locks = manager.dict ()) дочернему процессу во время создания?
Я не очень хорош в этом переполнении стека, поэтому, если есть какая-либо дополнительная информация, которую я могу предоставить, пожалуйста, дайте мне знать.Я ожидал, что приведенный выше фрагмент кода заключается в том, что, получив блокировку fcntl в заданном дочернем процессе, передав заблокированный объект файла в tarfile.open, добавив файл с помощью tarfile.addfile (я также попробовал обычный старый tarfile.add с тем же результатом), и после этого закрытие / разблокировка файла будет работать.Я подозреваю, что что-то в блокировке файла молча препятствует операции tarfile.add, потому что файл, который запускает этот код, может определить, что файл успешно добавлен.Никаких исключений не возникает, но когда я вытаскиваю этот файл и проверяю его - нада.