Использование многопроцессорной обработки с помощью метода void method / setter - PullRequest
0 голосов
/ 09 июля 2019

Я все еще новичок в многопроцессорности, но за последние пару дней много читал и хочу посмотреть, возможно ли что-то, что я имел в виду, с помощью многопроцессорности.

Множество примеров многопроцессорностионлайн выглядит следующим образом:

def worker():
    print('Worker')

if __name__ == '__main__':
    jobs = []

    for i in range(5):
        p = multiprocessing.Process(target=worker)
        jobs.append(p)
        p.start()

Но примеры методов многопроцессорной обработки всегда возвращают или распечатывают что-то!Есть ли способ, которым я могу сделать следующее?

import multiprocessing

class Worker():
    def __init__(self):
        self.level=0
    def setLevel(self,val):
        self.level=val

def method(worker, level):
     worker.setLevel(level)

if __name__ == '__main__':
    jobs = []
    for i in range(5):
        jobs.append(Worker())
    pool=multiprocessing.Pool()
    for i in range(5):
       worker=jobs[i]
       res = pool.apply_async(method, args=(worker,i,))
    pool.close()
    pool.join()
    for worker in jobs:
        print(worker.level)

Я знаю, apply_async возвращает объект результата, значение которого вы можете получить с помощью Result.get(), но это не кажется полезным в такой настройкекак тот, который я описал.

Когда я выполняю следующий код, я получаю 0 0 0 0 0 вместо желаемого 0 1 2 3 4 результата.

1 Ответ

1 голос
/ 09 июля 2019

Вообще говоря, нет необходимости возвращать что-то из функции, переданной в Pool.appy_async(), но в этом случае необходимо обновить соответствующий объект Worker в списке jobs, который существует только в основном процессе..

Это потому, что когда multiprocessing, каждый процесс выполняется в своем собственном пространстве памяти, что означает, что вы не можете разделять глобальные переменные между ними.Есть способы симулировать это, но, как правило, это влечет за собой много накладных расходов и может фактически лишить выгоды от многопроцессорной обработки.Каждый подпроцесс получает копию объекта Worker.

Принимая это во внимание, вот один из способов заставить ваш код работать.Функция method() теперь возвращает (копию) обновленного объекта Worker главному процессу, который сохраняет все объекты результатов, связанные с каждым, в отдельном списке с именем results.Когда все задания были обработаны после вызова pool.join(), этот список затем используется для замены каждого Worker объекта, который был первоначально помещен в список jobs - только для него только отображается какони сами обновились.

import multiprocessing


class Worker():
    def __init__(self):
        self.level = 0

    def setLevel(self,val):
        self.level = val


def method(worker, level):
    worker.setLevel(level)
    return worker  # ADDED - return updated Worker object.


if __name__ == '__main__':
    jobs = []
    for i in range(5):
        jobs.append(Worker())

    results = []
    pool = multiprocessing.Pool()
    for i in range(5):
        worker = jobs[i]
        results.append(pool.apply_async(method, (worker, i)))

    pool.close()
    pool.join()

    # Update Workers in jobs list.
    for i, result in enumerate(results):
        jobs[i] = result.get()  # Replace workers with their updated version.

    for worker in jobs:
        print(worker.level)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...