Пул внутри класса в Python

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

from multiprocessing import Pool

class SeriesInstance(object):
    def __init__(self):
        self.numbers = [1,2,3]
    def F(self, x):
        return x * x
    def run(self):
        p = Pool()
        print p.map(self.F, self.numbers)


ins = SeriesInstance()
ins.run()

Выходы:

Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib64/python2.7/threading.py", line 551, in __bootstrap_inner
    self.run()
  File "/usr/lib64/python2.7/threading.py", line 504, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/usr/lib64/python2.7/multiprocessing/pool.py", line 319, in _handle_tasks
    put(task)
PicklingError: Can't pickle <type 'instancemethod'>: attribute lookup __builtin__.instancemethod failed

А потом зависает.


person user58925    schedule 31.08.2015    source источник


Ответы (3)


Похоже, что из-за того, как функция передается в рабочие потоки (травление), вы, к сожалению, не можете использовать методы экземпляра. Моей первой мыслью было использовать лямбды, но оказалось, что встроенный консервант может ' t также сериализуйте их. К сожалению, решение состоит в том, чтобы просто использовать функцию в глобальном пространстве имен. Вы все равно можете сделать его атрибутом экземпляра, взгляните:

from multiprocessing import Pool

def F(x):
    return x * x

class SeriesInstance(object):
    def __init__(self):
        self.numbers = [1,2,3]
        self.F = F

    def run(self):
        p = Pool()
        out = p.map(self.F, self.numbers)
        p.close()
        p.join()
        return out

if __name__ == '__main__':
    print SeriesInstance().run()
person Alex Sherman    schedule 01.09.2015
comment
Спасибо, но, похоже, возникла проблема. Когда я использую этот принцип в своем более крупном коде, он вылетает после нескольких итераций со следующей ошибкой OSError: [Errno 35] Ресурс временно недоступен - person user58925; 01.09.2015
comment
Думаю, ошибка связана с ошибками ОС при создании слишком большого количества процессов. Похоже, вам нужно правильно закрыть свои пулы, когда вы закончите с ними, но это всего лишь предположение. В зависимости от вашего фактического кода, который вы должны предоставить, если можете, вы можете использовать один пул, который вы передаете для запуска в качестве параметра, или только для каждого SeriesInstance вы должны закрыть их пулы, когда вы закончите с ними. - person Alex Sherman; 02.09.2015
comment
Обычно вы должны ограничить размер вашего пула p = mp.Pool (mp.cpu_count ()). Это прекрасно работает. - person Steve Lihn; 01.07.2021

Вы также можете использовать многопроцессорность со статическими функциями в классе.

person stardust    schedule 08.03.2020

У вас ошибка, потому что pickle не может сериализовать метод экземпляра. Поэтому вам следует использовать этот крошечный обходной путь:

from itertools import repeat
from multiprocessing import Pool


class SeriesInstance:
    def __init__(self):
        self.numbers = [1, 2, 3]

    def F(self, x):
        return x * x

    def run(self):
        p = Pool()
        print(list(p.starmap(SeriesInstance.F, zip(repeat(self), self.numbers))))


if __name__ == '__main__':
    SeriesInstance().run()

person Юра Миронов    schedule 30.10.2020
comment
Добро пожаловать в SO! Вы можете улучшить качество своего ответа с помощью нескольких пояснений. - person Timus; 30.10.2020
comment
В этом примере будут использоваться все ядра для ускорения вычислений в методе экземпляра. Оно работает. - person Steve Lihn; 08.07.2021