Печать выходов функции Парелла в истинном порядке с Python - PullRequest
0 голосов
/ 11 марта 2019

Нужно напечатать все по порядку, для параллельного скрипта Python. Обратите внимание, что c3 напечатан до b2 - не в порядке. Любой способ сделать функцию ниже с функцией ожидания? При повторном запуске иногда порядок печати подходит для более коротких партий. Однако, ищем воспроизводимое решение этой проблемы.

from joblib import Parallel, delayed, parallel_backend
import multiprocessing

testFrame = [['a',1], ['b', 2], ['c', 3]]

def testPrint(letr, numbr):
  print(letr + str(numbr))
  return letr + str(numbr)

with parallel_backend('multiprocessing'):
  num_cores = multiprocessing.cpu_count()
  results = Parallel(n_jobs = num_cores)(delayed(testPrint)(letr = testFrame[i][0], 
        numbr = testFrame[i][1]) for i in range(len(testFrame))) 

print('##########')
for test in results:
  print(test)

Выход:

b2
c3
a1
##########
a1
b2
c3

Seeking:
a1
b2
c3
##########
a1
b2
c3

1 Ответ

1 голос
/ 12 марта 2019

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

Если вы распараллеливаете (?) Задачу / функцию с последовательностью аргументов и хотите изменить порядок результатов в соответствии с порядком исходной последовательности, вы можете передать информацию о последовательности в задачу / функцию, которая будетбыть возвращен заданием и может быть использован для восстановления исходного заказа.

Если функция original выглядит следующим образом:

def f(arg):
    l,n = arg
    #do stuff
    time.sleep(random.uniform(.1,10.))
    result = f'{l}{n}'
    return result

Рефакторинг функции: принять информацию о последовательности и передать ее с возвратомзначение.

def f(arg):
    indx, (l,n) = arg
    time.sleep(random.uniform(.1,10.))
    result = (indx,f'{l}{n}')
    return result

enumerate можно использовать для добавления информации о последовательности в последовательность данных:

originaldata = list(zip('abcdefghijklmnopqrstuvwxyz', range(26)))
dataplus = enumerate(originaldata)

Теперь аргументы имеют вид (index,originalarg) ... (0, ('a',0'), (1, ('b',1)).

И возвращенные значения из мультипроцессов выглядят так (если собраны в список) -

[(14, 'o14'), (23, 'x23'), (1, 'b1'), (4, 'e4'), (13, 'n13'),...]

, которые легко сортируются по первому элементукаждый результат, key=lambda item: item[0], и значения, которые вы действительно хотите получить, выбрав вторые элементы после сортировки results = [item[1] for item in results].

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...