Безопасно ли передавать функцию или экземпляр класса в «целевой» аргумент многопроцессорной обработки. Процесс без риска плотного копирования? - PullRequest
0 голосов
/ 31 октября 2018

Интересно, можно ли передать функцию другого класса, которая имеет много импортов и довольно плотную, в качестве экземпляра multiprocessing.Process в качестве аргумента? Обратите внимание, что я собираюсь запустить этот код на Unix-машине, и поэтому Process будет fork, а не spawn. Вот пример:

#class1.py
from class3 import Class3
class Class1(object):
    def __init__(self):
        self.class3Instance = Class3()

    def func1(self):
        self.class3Instance.func3()

#class3.py
import numpy as np
import pandas
import cv2 # OpenCV library
# there are many other things that I am importing here

class Class3(object):
    def __init__(self):
        pass

    def func3(self):
        np.random.seed(1)
        print ('func3 changed the random seed')

#class2.py
import numpy as np
class Class2(object):
    def __init__(self):
        pass

    def func2(self, funcInput):
        funcInput()

#main.py
from class1 import Class1
from class2 import Class2

class1Instance = Class1()
class2Instance = Class2()
from multiprocessing import Process

class2Process = Process(target=class2Instance.func2, kwargs={'funcInput': class1Instance.func1})
class2Process.start()
class2Process.join()

Этот пример, кажется, хорошо работает для такого небольшого масштаба, но я боюсь, что multiprocessing.Process не сможет правильно fork вещи в этом случае и вместо этого попытаться сделать плотную копию классов в иерархии. Я не хочу, чтобы это было так. Это правильный аргумент?

1 Ответ

0 голосов
/ 31 октября 2018

multiprocessing.Process, используемый в режиме fork, не нужно будет использовать привязанный метод (что потребовало бы выбора экземпляра), поэтому будут оплачены минимальные первоначальные затраты. Нет никакой задокументированной гарантии этого AFAICT, но реализация CPython с использованием fork не делает этого, и у них нет причин для этого, поэтому я не вижу, чтобы они убирали эту функцию, когда нечего было получить это.

Тем не менее, природа дизайна подсчета ссылок CPython (с циклическим сборщиком мусора для обработки сбоев подсчета ссылок) такова, что заголовок объекта для всех объектов Python будет соприкасаться с перерывами, что приведет к тому, что любая страница, содержащая небольшой объект, который нужно скопировать, поэтому, хотя работа ЦП, связанная с фактическим выполнением цикла сериализации / десериализации, не произойдет, длительное выполнение Process обычно приводит к разделению нескольких страниц с родительским процессом.

Также обратите внимание, что multiprocessing.Process в режиме fork - единственный раз, когда вы извлекаете из этого пользу. Методы запуска forkserver и spawn не получают копии родительских страниц при копировании при записи, и поэтому не могут принести пользу, и такие методы multiprocessing.Pool, как apply / apply_async и различные map - например, функции всегда выбирают как вызываемую функцию, так и ее аргументы (поскольку рабочие процессы не знают, какие задачи им будет предложено выполнить, когда они разветвлены, а объекты могли измениться после -привет, так что он всегда их переизлучает).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...