Почему mulitprocessing.Pool запускается, но никогда не завершается?

Я пытаюсь использовать mulitprocessing.Pool для ускорения выполнения функции в диапазоне входных данных. Кажется, процессы были вызваны, поскольку мой диспетчер задач указывает на значительное увеличение использования моего ЦП, но задача никогда не завершается. Никаких исключений никогда не возникает, во время выполнения или иным образом.

from multiprocessing import Pool

def f(x):
    print(x)
    return x**2

class Klass:
    def __init__(self):
        pass

    def foo(self):
        X = list(range(1, 1000))
        with Pool(15) as p:
            result = p.map(f, X)

if __name__ == "__main__":
    obj = Klass()
    obj.foo()
    print("All Done!")

Интересно, что, несмотря на рост загрузки ЦП, print(x) никогда ничего не выводит на консоль.

Я переместил функцию f за пределы класса, как было предложено здесь, чтобы бесполезно. Я также пытался добавить p.close() и p.join(), но безуспешно. Использование других методов класса Pool, таких как imap, приводит к TypeError: can't pickle _thread.lock objects ошибкам и, кажется, делает шаг в сторону от примера использования во введении Документация по многопроцессорной обработке Python.

Добавляя путаницы, если я попытаюсь запустить приведенный выше код достаточное количество раз (убивая зависшее ядро ​​​​после каждой попытки), код начнет стабильно работать, как и ожидалось. Обычно требуется около двадцати попыток, прежде чем это «щелкнет» на месте. Перезапуск моей IDE возвращает теперь функциональный код обратно в прежнее неисправное состояние. Для справки: я использую дистрибутив Anaconda Python (Python 3.7) со Spyder IDE в Windows 10. Мой ЦП имеет 16 ядер, поэтому Pool(15) не требует больше процессов, чем ядер ЦП. Однако запуск кода в другой среде IDE, такой как Jupyter Lab, приводит к тем же неверным результатам.

Другие предположили, что это может быть недостатком самого Spyder, но предложение использовать mulitprocessing.Pool вместо mulitprocessing.Process тоже не работает.


person NolantheNerd    schedule 07.05.2020    source источник
comment
Я знаю, что это не поможет ответить на вопрос, но определение __init__ излишне, поскольку оно будет унаследовано от object.   -  person Daniel Walker    schedule 07.05.2020
comment
Не могли бы вы добавить оператор печати внутри f? Например, print(x). Таким образом, вы могли видеть процессы, которые запускаются.   -  person Daniel Walker    schedule 07.05.2020
comment
Абсолютно! Добавление print(x) к f ничего не выводит на консоль.   -  person NolantheNerd    schedule 07.05.2020
comment
Хм. Я тогда ничего не получил. Дословный запуск вашего кода с терминала на моем Mac работает отлично.   -  person Daniel Walker    schedule 07.05.2020


Ответы (2)


Может быть связано с этим из документ питона:

Примечание. Для работы этого пакета требуется, чтобы дочерние элементы могли импортировать модуль main. Это описано в Руководстве по программированию, однако стоит упомянуть здесь. Это означает, что некоторые примеры, такие как примеры multiprocessing.pool.Pool, не будут работать в интерактивном интерпретаторе.

а затем этот комментарий к их примеру:

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

ОБНОВЛЕНИЕ: информация, найденная здесь, похоже, подтверждает, что использование пула из интерактивного интерпретатора будет иметь переменный успех. Это руководство также распространено...

... руководство [состоит] в том, чтобы всегда использовать функции/классы, определения которых можно импортировать.

Это решение описано здесь и работает для меня (каждый раз), используя ваш код.

person jayveesea    schedule 07.05.2020
comment
Это может быть так, но я, кажется, не вижу никаких трассировок, о которых они упоминали. - person NolantheNerd; 07.05.2020
comment
куда ты смотришь? для jupyter вам нужно посмотреть в консоли, из которой вы его запустили. Я получаю сообщение Не могу получить атрибут 'f' в ‹модуле 'main' (встроенный)› при запуске вашего кода. - person jayveesea; 07.05.2020
comment
и я получаю то же сообщение, когда запускаю пример python в jupyter. мог бы также объяснить, почему он когда-нибудь заработает (использует 15 других ядер). - person jayveesea; 07.05.2020
comment
Я исправляюсь. Внутри консоли, используемой для запуска Jupyter, я получаю ту же ошибку, что и вы: AttributeError: Can't get attribute 'f' on <module '__main__' (built-in)>. К сожалению, я не могу объяснить, почему после нескольких убийств ядра оно начинает работать. Мне не нужно менять какой-либо из приведенных выше кодов. Он просто спонтанно начинает работать, как и ожидалось. - person NolantheNerd; 07.05.2020
comment
см. также здесь - person jayveesea; 07.05.2020

Похоже, это может быть проблема как со Spyder, так и с Jupyter. Если вы запустите приведенный выше код напрямую в консоли, все будет работать, как задумано.

person NolantheNerd    schedule 07.05.2020