Обновление переменной-члена объекта при использовании многопроцессорного пула - PullRequest
0 голосов
/ 19 февраля 2020

У меня есть класс B, который состоит из другого класса A.

В классе B Я использую многопроцессорный пул для вызова метода из класса A. Этот метод обновляет переменную-член A (которая является dict).

Когда я распечатываю эту переменную-член, она, кажется, не была обновлена. Вот код, описывающий проблему:

import multiprocessing as mp

class A():
    def __init__(self):
        self.aDict = {'key': 0}

    def set_lock(self, lock):
        self.lock = lock

    def do_work(self, item):
        print("Doing work for item: {}".format(item) )
        self.aDict['key'] += 1

        return [1,2,3] # return some list

class B():
    def __init__(self):
        self.objA = A()

    def run_with_mp(self):
        items=['item1', 'item2']
        with mp.Pool(processes=mp.cpu_count()) as pool:
            result = pool.map_async(self.objA.do_work, items)
            result.wait()
            pool.terminate()

        print(self.objA.aDict)

    def run(self):
        items=['item1', 'item2']
        for item in items:
            self.objA.do_work(item)

        print(self.objA.aDict)

if __name__ == "__main__":
    b = B()
    b.run_with_mp() # prints {'key': 0}
    b.run()         # prints {'key': 2}

b.run_with_mp() печать {'key': 0} вся b.run() печать {'key': 2}. Я думал, что версия многопроцессорного пула также будет делать то же самое, поскольку объект self.objA имеет область видимости для полного класса B, в котором работает многопроцессорный пул.

Я думаю, что каждый работник пула видит свою версию self.objA, которая отличается от версии основного потока программы. Есть ли способ заставить всех работников обновить общую переменную?

1 Ответ

0 голосов
/ 19 февраля 2020

Вы близки к объяснению, действительно, каждый порожденный процесс имеет свою область памяти, это означает, что они независимы. При запуске do_work каждый процесс обновляет свою версию aDict, поскольку эта переменная не является общей. Если вы хотите предоставить общий доступ к переменной, самый простой способ - использовать Manager, например:

import multiprocessing as mp

class A():
    def __init__(self):
        self.aDict = mp.Manager().dict({'key': 0})

    def set_lock(self, lock):
        self.lock = lock

    def do_work(self, item):
        print("Doing work for item: {}".format(item) )
        self.aDict['key'] += 1

        return [1,2,3] # return some list

class B():
    def __init__(self):
        self.objA = A()

    def run_with_mp(self):
        items=['item1', 'item2']
        with mp.Pool(processes=mp.cpu_count()) as pool:
            result = pool.map_async(self.objA.do_work, items)
            result.wait()
            pool.terminate()

        print(self.objA.aDict)

    def run(self):
        items=['item1', 'item2']
        for item in items:
            self.objA.do_work(item)

        print(self.objA.aDict)

if __name__ == "__main__":
    b = B()
    b.run_with_mp() # prints {'key': 2}
    b.run()         # prints {'key': 4}

Я изменил ваш пример, чтобы использовать переменную aDict, поэтому каждый процесс обновит это свойство (run_with_mp и run методы). Вы можете прочитать больше в документах .

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