Создание параллели для цикла в Python - PullRequest
0 голосов
/ 24 августа 2018

Я смотрел на подобные вопросы, особенно этот ответ. Моя ситуация немного отличается, поэтому задаю вопрос.

import os
import multiprocessing as mp

def fun1(str1):
 #function def

if __name__ == '__main__':


    pl1 = mp.Pool(processes=2)
    pl2 = mp.Pool(processes=2)

for (d1,d2,d3) in os.walk('dirname'):
    for d4 in d2:
        pl1.map(fun1,d4)

    for d5 in d3:
        pl2 .map(fun1,d5)
#

Я получаю имена файлов и каталогов в виде строк и передаю их fun1(). Но проблема в том, что если я использую pl1.map(fun1,d4), похоже, что python отделяет каждый символ строки и передает отдельный символ в fun1(). Я хочу, чтобы целые строки d4,d5 передавались на fun1() и параллельно, чтобы сократить время выполнения. Я создал 2 пула pl1,pl2, чтобы их можно было использовать отдельно в цикле for верхнего уровня без каких-либо проблем.

Есть идеи, как решить эту проблему?

Ответы [ 2 ]

0 голосов
/ 24 августа 2018

Насколько я понимаю, многопроцессорный модуль оптимизирован благодаря использованию C за кулисами.Поэтому работа с ctypes может стать решением вашей проблемы:

from ctypes import c_char_p
from multiprocessing import Process, Manager, Value, Pool

manager = Manager()
pool = Pool(processes=2)
pool2 = Pool(processes=2)
for (d1,d2,d3) in os.walk('dirname'):
    for d4 in d2:
        d4_string = manager.Value(c_char_p, d4)
        pool.map(fun1, d4_string)
        pool.join()

    for d5 in d3:
        d4_string = manager.Value(c_char_p, d4)
        pool2.map(fun1, d4_string)
        pool2.join()
0 голосов
/ 24 августа 2018

С многопроцессорная документация для метода Pool.map:

Этот метод разбивает итерацию на несколько кусков, которые он отправляет в пул процессов как отдельные задачи.

Таким образом, она принимает строку d4 как итеративную и отправляет ее процессам по буквам (одна за другой). Вы, вероятно, ищете Pool.apply_async:

pl1.apply_async(fun1, d4)

Или просто передайте d2 в пул (без использования цикла for " для d4 в d2 "):

pl1.map(fun1, d2)

Изменить - окончательный код может выглядеть следующим образом:

for (d1,d2,d3) in os.walk('dirname'):
    pl1.map(fun1,d2)
    pl2.map(fun1,d3)
...