Многопроцессорность Python с пафосом

Я пытаюсь использовать пафос Python для выделения вычислений в отдельные процессы, чтобы ускорить их с помощью многоядерного процессора. Мой код организован так:

class:
   def foo(self,name):
    ...
    setattr(self,name,something)
    ...
   def boo(self):
      for name in list:
         self.foo(name)

Так как у меня были проблемы с травлением multiprocessing.Pool, решил попробовать пафосно. Пробовал, как предлагалось в предыдущих темах:

import pathos.multiprocessing

но выдавало ошибку: Нет многопроцессорности модуля - чего не могу найти в последней пафосной версии.

Затем я попытался изменить метод boo:

def boo(self):
 import pathos
 pathos.pp_map.pp_map(self.foo,list)

Теперь ошибки нет, но foo не работает - экземпляр моего класса не имеет новых атрибутов. Пожалуйста, помогите мне, потому что я понятия не имею, куда двигаться дальше, после дня, потраченного на это.


person user3708829    schedule 26.09.2014    source источник


Ответы (2)


Я pathos автор. Я не уверен, что вы хотите сделать из кода выше. Тем не менее, я, возможно, могу пролить свет. Вот аналогичный код:

>>> from pathos.multiprocessing import ProcessingPool
>>> class Bar:
...   def foo(self, name):
...     return len(str(name))
...   def boo(self, things):
...     for thing in things:
...       self.sum += self.foo(thing)
...     return self.sum
...   sum = 0
... 
>>> b = Bar()
>>> results = ProcessingPool().map(b.boo, [[12,3,456],[8,9,10],['a','b','cde']])
>>> results
[6, 4, 5]
>>> b.sum
0

Итак, что происходит выше, так это то, что вызывается метод boo экземпляра Bar b, где b.boo передается новому процессу Python, а затем оценивается для каждого из вложенных списков. Как видите, результаты верны… len("12")+len("3")+len("456") равно 6 и так далее.

Однако вы также можете видеть, что когда вы смотрите на b.sum, это загадочным образом все еще 0. Почему b.sum по-прежнему равно нулю? Ну, что делает multiprocessing (и, следовательно, также pathos.multiprocessing), так это делает КОПИЯ всего, что вы передаете через карту в другой процесс python… а затем вызывается скопированный экземпляр (параллельно) и возвращается любые результаты вызываются вызываемым методом. Обратите внимание, что вы должны ВОЗВРАТИТЬ результаты, либо распечатать их, либо зарегистрировать, либо отправить в файл, либо иным образом. Они не могут вернуться к исходному экземпляру, как вы могли бы ожидать, потому что это не исходный экземпляр, отправленный другим процессорам. Копии экземпляра создаются, а затем удаляются — у каждой из них был увеличен атрибут sum, но исходный `b.sum' не тронут.

Тем не менее, в pathos есть планы сделать что-то подобное вышеописанному, чтобы оно работало так, как вы могли бы ожидать, когда исходный объект IS обновляется, но он пока не работает так.

РЕДАКТИРОВАТЬ: Если вы устанавливаете с pip, обратите внимание, что последней выпущенной версии pathos несколько лет, и она может быть установлена ​​неправильно или могут быть установлены не все подмодули. Новый выпуск pathos ожидается, но до тех пор лучше получить последнюю версию кода с github и установить оттуда. Ствол по большей части стабильно находится в стадии разработки. Я думаю, что ваша проблема могла заключаться в том, что не все пакеты были установлены из-за «новой» pip -- «старой» pathos несовместимости при установке. Если pathos.multiprocessing отсутствует, это наиболее вероятный виновник.

Получите pathos с github здесь: https://github.com/uqfoundation/pathos

person Mike McKerns    schedule 28.10.2014
comment
У меня та же проблема, что и у ОП. Я могу сделать import pathos, но import pathos.multiprocessing выдает ошибку, что модуль не найден. Что может быть причиной этого? - person sashkello; 05.11.2014
comment
Проблема в том, что я не понимаю вопрос ОП… из-за некоторого барьера на английском языке, а также из-за минимальных примеров кода. Может быть, я могу попробовать другой подход. Возможно, не все зависимости были установлены. Вы можете import processing? Как насчет from processing.pool import Pool? Как насчет from pathos.helpers import mp_helper или from pathos.helpers import ProcessPool? А как насчет import pp и from pathos.helpers import pp_helper? - person Mike McKerns; 05.11.2014
comment
from pathos.helpers import * дает No module named helpers. Как-то не весь пафос мне доступен и кажется ОП. Я установил его из pip, это последняя версия. - person sashkello; 05.11.2014
comment
В пакете у меня есть ядро, хосты, Launcher, LauncherSCP, LauncherSSH, pp_map, Server, Tunnel, util, XMLRPCRequestHandler, XMLRPCServer. Вот и все, никаких хелперов, никакой многопроцессорности. - person sashkello; 05.11.2014
comment
Я не вижу многопроцессорности в файле tgz, который я скачал с официального сайта, но он присутствует в git. попробую переустановить оттуда... - person sashkello; 05.11.2014
comment
Да, теперь это работает. По какой-то причине в официальном tgz отсутствуют некоторые подмодули. Установка из git сработала для меня. - person sashkello; 05.11.2014
comment
То же самое, пришлось установить из репозитория git, а не из файла tgz. - person Brideau; 23.01.2015
comment
@Brideau: я сейчас разбиваю pathos еще на несколько пакетов (в основном все нестандартные зависимости), чтобы убедиться, что все pip можно установить. Новые выпуски должны появиться в ближайшее время. - person Mike McKerns; 24.01.2015
comment
обновление: все pip можно установить и уже давно. - person Mike McKerns; 14.03.2017
comment
Привет @MikeMcKerns, интересно, в чем разница между ParallelPool и ProcessingPool? Если они разные, в каких случаях я должен использовать любой из них? Заранее спасибо. - person LifeWorks; 27.07.2017
comment
Разница в том, что ProcessingPool использует multiprocess, а ParallelPool использует ppft. Первый предназначен для параллельных вычислений, а второй может использоваться через сетевое соединение. - person Mike McKerns; 27.07.2017

Вот как я это делаю: я помещаю функцию для параллельного запуска вне класса и передаю объект в качестве аргумента при вызове pool.map. Затем я возвращаю объект для переназначения.

from pathos.multiprocessing import ProcessingPool


def boo(args):
    b, things = args
    for thing in things:
        b.sum += b.foo(thing)
    return [b, b.sum]

class Bar:
    def __init__(self):
       self.sum = 0
    def foo(self, name):
       return len(str(name))

pool = ProcessingPool(2)
b1 = Bar()
b2 = Bar()
print(b1, b2)

results = pool.map(boo, [[b1, [12,3,456]],[b2, ['a','b','cde']]])

b1, b1s = results[0]
b2, b2s = results[1]
print(b1,b1s,b1.sum)
print(b2, b2s, b2.sum)

Выход:

(<__main__.Bar instance at 0x10b341518>, <__main__.Bar instance at 0x10b341560>)
(<__main__.Bar instance at 0x10b3504d0>, 6, 6)
(<__main__.Bar instance at 0x10b350560>, 5, 5)

Обратите внимание, что b1 и b2 больше не совпадают с тем, что было до вызова map, потому что их копии были созданы для передачи, как описано @Mike McKerns. Однако значения всех их атрибутов остаются нетронутыми, поскольку они были переданы, возвращены и переназначены.

person madvn    schedule 07.12.2020