Подтвердить что ты не робот

Почему важно защищать основной цикл при использовании joblib.Parallel?

Документы joblib содержат следующее предупреждение:

В Windows важно защитить основной цикл кода до избегать рекурсивного нереста подпроцессов при использовании joblib.Parallel. Другими словами, вы должны написать такой код:

import ....

def function1(...):
    ...

def function2(...):
    ...

... if __name__ == '__main__':
    # do stuff with imports and functions defined about
    ...

Никакой код не должен выполняться вне блоков "if __name__ ==" __main__ ", только импорт и определения.

Вначале я предполагал, что это было просто для предотвращения случайного случайного случая, когда функция, переданная в joblib.Parallel, называлась модулем рекурсивно, что означало бы, что это была обычно хорошая практика, но часто не нужна. Однако мне не имеет смысла, почему это будет только угрозой для Windows. Кроме того, этот ответ, как представляется, указывает на то, что отказ от защиты основного цикла привел к тому, что код работает в несколько раз медленнее, чем в противном случае, для очень простой нерекурсивной проблемы.

Из любопытства я провел суперпростой пример неловко параллельного цикла из документов joblib, не защищая основной цикл в окне окна. У моего терминала была спама следующая ошибка, пока я не закрыл ее:

ImportError: [joblib] Attempting to do parallel computing without protecting your import on a system that does not suppo
rt forking. To use parallel-computing in a script, you must protect you main loop using "if __name__ == '__main__'". Ple
ase see the joblib documentation on Parallel for more information

Мой вопрос: Что делать с реализацией windows joblib требует, чтобы основной цикл был защищен в каждом случае?

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

Наконец, я хочу отметить, что это чисто академическое; Я понимаю, почему это обычно хорошая практика, чтобы написать один код таким образом и будет продолжать делать это независимо от joblib.

4b9b3361

Ответ 1

Это необходимо, потому что Windows не имеет fork(). Из-за этого ограничения Windows необходимо повторно импортировать ваш модуль __main__ во все дочерние процессы, которые он порождает, чтобы воссоздать родительское состояние в дочернем. Это означает, что если у вас есть код, который порождает новый процесс на уровне модуля, он будет рекурсивно выполняться во всех дочерних процессах. Защитник if __name__ == "__main__" используется для предотвращения повторного выполнения кода в области видимости модуля в дочерних процессах.

Это не обязательно для Linux, потому что у него есть fork(), что позволяет ему развивать дочерний процесс, который поддерживает одно и то же состояние родителя, без повторного импорта модуля __main__.