Цикл параллельной обработки с использованием многопроцессорного пула

Я хочу обрабатывать большой цикл for параллельно, и из того, что я прочитал, лучший способ сделать это - использовать библиотеку многопроцессорности, которая входит в стандартную комплектацию с Python.

У меня есть список из около 40 000 объектов, и я хочу обрабатывать их параллельно в отдельном классе. Причина этого в отдельном классе объясняется главным образом тем, что я читал здесь.

В одном классе у меня есть все объекты в списке и через функции multiprocessing.Pool и Pool.map. Я хочу выполнять параллельные вычисления для каждого объекта, заставляя его проходить через другой класс и возвращать значение.

# ... some class that generates the list_objects
pool = multiprocessing.Pool(4)
results = pool.map(Parallel, self.list_objects)

И тогда у меня есть класс, который я хочу обработать каждый объект, переданный функцией pool.map:

class Parallel(object):
    def __init__(self, args):
        self.some_variable          = args[0]
        self.some_other_variable    = args[1]
        self.yet_another_variable   = args[2]
        self.result                 = None

    def __call__(self):
        self.result                 = self.calculate(self.some_variable)

Причина, по которой у меня есть метод вызова, связана с сообщением, которое я связал ранее, но я не уверен, что правильно его использую, поскольку он, кажется, не имеет никакого эффекта. Я не получаю значение self.result.

Любые предложения? Спасибо!

Ответ 1

Используйте, если это возможно, обычную функцию, а не класс. Используйте класс только тогда, когда есть явное преимущество для этого.

Если вам действительно нужно использовать класс, то, учитывая вашу настройку, передайте экземпляр Parallel:

results = pool.map(Parallel(args), self.list_objects)

Так как экземпляр имеет метод __call__, сам экземпляр может быть вызван, как функция.


Кстати, __call__ должен принять дополнительный аргумент:

def __call__(self, val):

поскольку pool.map по существу будет вызывать параллель

p = Parallel(args)
result = []
for val in self.list_objects:
    result.append(p(val))

Ответ 2

Pool.map просто применяет функцию (фактически, вызываемую) параллельно. Он не имеет понятия об объектах или классах. Поскольку вы передаете ему класс, он просто вызывает __init__ - __call__ никогда не выполняется. Вам нужно либо явно вызвать его из __init__, либо использовать pool.map(Parallel.__call__, preinitialized_objects)