Ошибка выполнения: ошибка многопроцессорной обработки python

#python #windows #multiprocessing

Вопрос:

Я пытаюсь использовать параллельную обработку в python, используя следующий код:

 import os
import datetime
import numpy as np
import FarimaModule
from  statsmodels.tsa.arima.model import ARIMA
import matplotlib.pyplot as plt
import multiprocessing as mp

# Here I define some variables: p_max,q_max,m_list,wlen,mstep,fs, listFile

def implement(fname,p_max,q_max,m_list,wlen,mstep,fs):
    # It is a really long code

# run the function 'implement' in parallel for different values of the input variable 'fname'
pool = mp.Pool(10)
results = [pool.apply(implement, args=(fname,p_max,q_max,m_list,wlen,mstep,fs)) for fname in listFile]
pool.close()
 

Но он выдает следующую ошибку:

     An attempt has been made to start a new process before the
    current process has finished its bootstrapping phase.

    This probably means that you are not using fork to start your
    child processes and you have forgotten to use the proper idiom
    in the main module:

        if __name__ == '__main__':
            freeze_support()
            ...

    The "freeze_support()" line can be omitted if the program
    is not going to be frozen to produce an executable.
 

Другие опубликовали вопросы с той же ошибкой. Но я не могу реализовать размещенные там решения, поскольку неясно, как мне адаптировать эти решения для моего кода.

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

1. Вы добавили if __name__ == '__main__': , как указано в сообщении об ошибке? Документация по многопроцессорной обработке объясняет необходимость этой строки.

2. Более конкретно, последние три строки должны выполняться только в основном потоке. В вашем случае каждый вновь запущенный поток будет считывать ваш файл и запускать еще один пул из десяти потоков. Код создания пула должен выполняться только один раз.

3. Спасибо за предложение. Я не смог найти mp.Pool.apply() метод, проиллюстрированный там. Но pool.map() , похоже, работает.

4. @FrankYellin Я добавлял if __name__ == '__main__':' after pool = mp.Pool . That is why it was not working. It works if I add , если name == ‘ main ‘:’ перед этой строкой. Но теперь кажется, что он не выполняется последовательно, как обычный цикл for; он не распараллеливается.

Ответ №1:

В некоторых системах многопроцессорная обработка должна создавать новую копию python и импортировать ваш модуль, чтобы перейти к рабочему коду. Все, что находится на уровне модуля, выполняется снова… включая родительский код, который создает пул. Это было бы бесконечной рекурсией, за исключением того, что python обнаруживает проблему и дает вам удобный совет. Вы должны следовать за ним

 import os
import datetime
import numpy as np
import FarimaModule
from  statsmodels.tsa.arima.model import ARIMA
import matplotlib.pyplot as plt
import multiprocessing as mp

# Here I define some variables: p_max,q_max,m_list,wlen,mstep,fs, listFile

def implement(fname,p_max,q_max,m_list,wlen,mstep,fs):
    # It is a really long code

if __name__ == "__main__":
    # run the function 'implement' in parallel for different values of the input variable 'fname'
    pool = mp.Pool(10)
    results = [pool.apply(implement, args= 
       (fname,p_max,q_max,m_list,wlen,mstep,fs)) for fname in listFile]
    pool.close()
 

Сценарий python верхнего уровня всегда имеет имя "__main__" . При импорте подпроцессом он теперь является модулем и имеет другое имя.

pool.apply, скорее всего, не тот метод, который вам нужен — он ожидает завершения работы работника пула. map может быть лучшим выбором. Я вводил фрагменты (группы). В вашем случае при дорогостоящих вычислениях вам, вероятно, потребуется небольшой размер фрагмента. starmap просто map с несколькими параметрами.

 if __name__ == "__main__":
    # run the function 'implement' in parallel for different values of the input variable 'fname'
    with mp.Pool(10) as pool:
        results = pool.starmap(implement, 
            [(fname,p_max,q_max,m_list,wlen,mstep,fs)) 
                for fname in listFile],
            chunksize=1)
 

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

1. Этот код работает, но он не выполняет параллельную обработку. Он последовательно повторяет ‘fname`.

2. Это apply . Вы могли apply_async бы использовать или использовать map , как в примере, который я добавил.

3. pool.apply использует один поток. Если вы хотите использовать несколько потоков, вы должны либо выполнить несколько вызовов pool.apply , либо использовать один из вариантов pool.map() .

4. Спасибо всем. pool.starmap работает для меня.