Как вызвать функцию n раз с помощью многопроцессорной обработки

#python #multiprocessing #iteration

#python #многопроцессорная обработка #итерация

Вопрос:

Я хочу вызвать свою функцию n раз с многопроцессорной обработкой (чтобы сэкономить время) и сохранить результаты в массиве numpy:

 num=N # number of trials
results=np.zeros([N,2]) # array of results (2 because function produces 2 results)
def f(): #function with no arguments because the process is based on randomness
    ....
    return a, b #results are float64 type
 

Я хочу что-то вроде этого:

 for i in range(num):
    results[i]=f()
 

но с использованием многопроцессорной обработки. Есть ли способ?

Я пробовал это, но не сработало:

 from multiprocessing import Pool
if __name__ == '__main__':
    with Pool(15) as p:
        for i in range(num):
            result[i]=(p.map(f,iterable=i))
 

Ответ №1:

Вы можете добиться этого, вызвав apply_async() метод, который принадлежит Pool классу, и сохранив AsyncResult объекты в списке. Вам также нужно не забывать вызывать close() join() методы и . После завершения всех процессов вы можете собирать результаты из AsyncResult объектов. В следующем примере f() функция будет выполняться всего 100 раз, но одновременно будет запущено не более 4 процессов (не считая процесса, который запускает другие). Я уверен, что код можно оптимизировать еще больше, но это может быть хорошей отправной точкой.

 import multiprocessing as mp
import numpy as np


def f():
    # you perform your calculations here
    result = 0, 0  # this is only for testing
    return result


if __name__ == '__main__':
    count = 100
    async_results = []
    with mp.Pool(processes=4) as pool:
        for _ in range(count):
            async_results.append(pool.apply_async(f))
        pool.close()
        pool.join()

    results = np.zeros([count, 2])
    for i, async_result in enumerate(async_results):
        results[i] = async_result.get()
    print(results)
 

Комментарии:

1. Спасибо! Это работает, но у меня все еще есть проблема, и это довольно странно: если я ставлю count = 10, например, это работает отлично, но если я ставлю count = 100, процессор и память работают на максимальной мощности (так что это хорошо), но после этого, когда они заканчивают, код никогда не останавливается, и spyder зависает, выдаваяу меня нет результатов, и это невозможно остановить! Я должен отключить ее с помощью диспетчера задач. Есть идеи??

2. Я думаю, мне нужен способ ограничить количество процессов. В моем первом посте, где я пытался использовать mp. Пул, я установил 15 в качестве ограничения для процессора (или так я понимаю из документации), но здесь я не вижу ничего, что устанавливает ограничение. Я прав? Есть ли какое-либо решение?

3. Если вы установите значение count равным 100, он запустит 100 процессов одновременно, и они будут работать одновременно.

4. хорошо, но, как я вижу в коде, который вы предлагаете, вы вводите count=15 и получаете результат в виде массива с тем же размером строки ([count,2] ), поэтому я понял, что count означает испытания. Для моего кода мне нужно выполнить 100 000 проб, так как я могу изменить код для достижения этой цели? Заранее благодарю!!

5. У меня может быть идея. Я отредактирую ответ через мгновение.