У меня есть некоторый код Python, в котором у нас есть несколько больших массивов. Мой родительский процесс загружает эти массивы в общую память с помощью / dev / shm tmpfs, записывает файл конфигурации с кучей путей и тому подобное на диск для дочерних / рабочих процессов, а затем использует многопроцессорный модуль python с помощью fork (). метод для порождения рабочих потомков.
В псевдокоде главный процесс примерно равен:
import mmap
import tempfile
import multiprocessing
fd1, path1 = tempfile.mkstemp(dir=some_directory)
memmap1 = mmap.mmap(fd1) #In python, this creates a duplicate file descriptor
write_big_array_into(memmap1)
config["fd1"] = fd1
config["path1"] = path1
pickle_config_to_disk(config, "/some/config/path")
worker_processes = []
for _ in range(num_cpus):
p = multiprocessing.Process(target=worker_function, args=(config_path))
#fork() occurs in the multiprocessing/popen_fork.py Popen._launch() method
p.start()
На данный момент, потому что Python создает дубликат файлового дескриптора при вызове mmap. mmap (), мой родительский процесс имеет 2 открытых файловых дескриптора. Поскольку я использую метод fork () для порождения дочерних процессов, все дочерние / рабочие процессы получают эти 2 существующих файловых дескриптора, плюс когда я вызываю mmap.mmap для дочернего процесса, я получаю третий!
Псевдокод ребенка / работника:
config = load_config_from_disk("/some/config/path")
#already inherited 2 fd's from the fork()
memmap1 = mmap.mmap(config["fd1"])
#despite using the existing fd1 from the parent, I now have 3 fd's in this worker for the same file!
Я подтвердил, что у родителя есть 2 fd для одного и того же файла, а у детей - 3 fd для одного и того же файла, изучив псевдо / proc / PID / fd -filesystem во время работы процессов.
Мой вопрос: что мне делать с этим? Я почти согласился бы иметь 1 ненужный дубликат у каждого родителя и ребенка, но кажется чрезмерным иметь 2 ненужных дубликата у детей. Есть ли способ обойти это без написания моего собственного расширения mmap C? (Кстати, это то, что сделал этот парень: https://bugs.python.org/issue10897)
Я подумал, что, возможно, смогу закрыть дубликат файлового дескриптора, созданного вызовами mmap.mmap (), но у меня нет не удалось получить доступ к атрибуту .fd - он не выглядит как объявленный publi c библиотекой CPython https://github.com/python/cpython/blob/master/Modules/mmapmodule.c. Я также подумал, что, возможно, я мог бы закрыть исходный fd и оставить скрытый fd внутри объекта mmap открытым, но тогда я не знаю значение fd, которое нужно дать детям, так как я не могу получить доступ к скрытому mmap fd (примечание Я знаю, что это немного философский вопрос, так как я мог бы просто дать детям путь вместо fd.
Я застрял с этими дополнительными файловыми дескрипторами? На данный момент, насколько я могу судить, они ничему не причиняют вреда, но я стараюсь быть хорошим покорным программистом и очищать свои ненужные ресурсы. Кажется глупым иметь (2 + 3 * num_children) дескрипторы открытыми, когда (1 + num_children) будет делать - и в моем конкретном случае c, он имеет (2 * num_arrays + 3 * num_arrays * num_children) вместо просто (num_arrays) + num_arrays * num_children) открываются дополнительные дескрипторы.