Написание параллельного цикла
Я пытаюсь запустить параллельный цикл на простом примере.
Что я делаю неправильно?
from joblib import Parallel, delayed
import multiprocessing
def processInput(i):
return i * i
if __name__ == '__main__':
# what are your inputs, and what operation do you want to
# perform on each input. For example...
inputs = range(1000000)
num_cores = multiprocessing.cpu_count()
results = Parallel(n_jobs=4)(delayed(processInput)(i) for i in inputs)
print(results)
Проблема с кодом заключается в том, что при выполнении в среде Windows в Python 3 он открывает num_cores
экземпляры python для выполнения параллельных заданий, но только один активен. Это не должно быть так, так как активность процессора должна быть на 100% вместо 14% (в i7-8 логических ядрах).
Почему лишние экземпляры ничего не делают?
Ответы
Ответ 1
Продолжая по вашему запросу предоставлять рабочий многопроцессорный код, я предлагаю вам использовать pool_map (если отложенная функциональность не важна), я Я приведу вам пример, если вы работаете над python3, стоит упомянуть, что вы можете использовать starmap.
Также стоит упомянуть, что вы можете использовать map_sync/starmap_async, если порядок возвращаемых результатов не должен соответствовать порядку входов.
import multiprocessing as mp
def processInput(i):
return i * i
if __name__ == '__main__':
# what are your inputs, and what operation do you want to
# perform on each input. For example...
inputs = range(1000000)
# removing processes argument makes the code run on all available cores
pool = mp.Pool(processes=4)
results = pool.map(processInput, inputs)
print(results)
Ответ 2
В Windows многопроцессорный модуль использует метод "spawn" для запуска нескольких процессов интерпретатора python. Это относительно медленно. Параллельно пытается быть умным при запуске кода. В частности, он пытается настроить размер партии, поэтому для выполнения партии требуется около половины секунды. (См. Аргумент batch_size в https://pythonhosted.org/joblib/parallel.html)
Ваша функция processInput()
работает так быстро, что Parallel определяет, что быстрее запускать задания поочередно на одном процессоре, чем разворачивать несколько интерпретаторов python и параллельно запускать код.
Если вы хотите заставить свой пример работать на нескольких ядрах, попробуйте установить batch_size в 1000 или сделать processInput()
более сложным, поэтому выполнение займет больше времени.
Изменить: рабочий пример в окнах с несколькими используемыми процессами (я использую окна 7):
from joblib import Parallel, delayed
from os import getpid
def modfib(n):
# print the process id to see that multiple processes are used, and
# re-used during the job.
if n%400 == 0:
print(getpid(), n)
# fibonacci sequence mod 1000000
a,b = 0,1
for i in range(n):
a,b = b,(a+b)%1000000
return b
if __name__ == "__main__":
Parallel(n_jobs=-1, verbose=5)(delayed(modfib)(j) for j in range(1000, 4000))