#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 работает для меня.