Как загрузить и выполнить процессы * по порядку * в Python? - PullRequest
0 голосов
/ 05 января 2019

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

Файл pool.map в стандартной библиотеке просто загружает все задания одновременно и выполняет их в произвольном порядке. Если было выполнено большое количество заданий, память переполнится.

Я прочитал официальную документацию Python3 , я пока не нашел связанных материалов.

Необходимая мне функция слишком детальна, я не думаю, что есть какая-либо третья библиотека, которая реализует эту функцию специально.

То, что я ожидал:

Существует четыре основных компьютера.

y = XXX.map(f,range(1,100))

если 1 ~ 4 не заканчивается, в системной памяти нет f (5) . Когда одна из этих четырех задач завершается, например, f (2), она загружает f (5) в положение f (2).

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

Ответы [ 2 ]

0 голосов
/ 06 января 2019

Прежде всего концепция карты, имеющей все подпроцессы в памяти, неверна, карта имеет весь повторяемый (входной) в памяти, превратив его в список. Однако он содержит только количество рабочих (пул), которые вы создаете, см. Пример.

Если проблема в том, что итерация длинная и занимает много памяти сама по себе, то лучше использовать imap, поскольку она не сохраняет всю итерацию в памяти, а просто берет следующую и передает ее работнику , Дополнительным преимуществом является то, что imap возвращает результаты напрямую (но по порядку), чтобы его можно было использовать основным процессом.

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

Пример:

import multiprocessing
import random
import time

def func(x):
    """
    1. Prints the process and input
    2. Waits a bit
    3. Uses a lot of memory
    4. Waits a random amount more
    """
    print(f'{multiprocessing.current_process()}: {x}')
    time.sleep(5)
    a = list(range(10000000))
    time.sleep(5 + random.randint(0, 5))

if __name__ == "__main__":
    pool = multiprocessing.Pool(processes=4)
    pool.map(func, range(10))

Выход:

<ForkProcess(ForkPoolWorker-1, started daemon)>: 0
<ForkProcess(ForkPoolWorker-2, started daemon)>: 1
<ForkProcess(ForkPoolWorker-3, started daemon)>: 2
<ForkProcess(ForkPoolWorker-4, started daemon)>: 3
<ForkProcess(ForkPoolWorker-2, started daemon)>: 4
<ForkProcess(ForkPoolWorker-4, started daemon)>: 5
<ForkProcess(ForkPoolWorker-3, started daemon)>: 6
<ForkProcess(ForkPoolWorker-1, started daemon)>: 7
<ForkProcess(ForkPoolWorker-4, started daemon)>: 8
<ForkProcess(ForkPoolWorker-3, started daemon)>: 9
0 голосов
/ 05 января 2019

Я заимствую из ответа Тредди здесь :

Вам просто нужно отредактировать значение процессов пула. Например, вот так:

from multiprocessing import Pool

def f(x):
    return x*x

if __name__ == '__main__':
    pool = Pool(processes=4)              # start 4 worker processes
    result = pool.apply_async(f, [10])    # evaluate "f(10)" asynchronously
    print result.get(timeout=1)           # prints "100" unless your computer is *very* slow
    print pool.map(f, range(10))          # prints "[0, 1, 4,..., 81]"

В этом примере нужно выполнить 10 заданий, но оно максимально для 4 процессов. Если вы оставите значение процесса пустым, оно будет использовать столько ресурсов, сколько было доступно.

Помогает ли это?

...