Я пытаюсь распараллелить некоторый код, который использует частичные функции для генерации случайных чисел для моделирования, над которым я работаю. Со следующим кодом:
#!/usr/bin/env python3
import functools
import random
import pathos
from itertools import starmap
from time import sleep
from datetime import datetime
def example(func1, func2):
sleep(1)
[a, b] = [func1(), func2()]
return (f"arg #1 is {round(a,2)}, arg #2 is {round(b,2)} at {datetime.now().time()}")
rand1 = functools.partial(random.uniform, 100, 199)
rand2 = functools.partial(random.uniform, 200, 299)
rand3 = functools.partial(random.uniform, 300, 399)
argsToRun = [(rand1, rand2), (rand2, rand3), (rand1, rand3)] # 3 ordered combinations...
print(f"running with a for loop...")
for args in argsToRun:
result = example(*args)
print(result)
print("\nRunning with itertools.starmap...")
results = starmap(example, argsToRun)
print("\n".join(results))
print("\nRunning with pathos.mp.starmap...")
with pathos.helpers.mp.Pool() as pool:
results = pool.starmap(example, argsToRun)
print("\n".join(results))
Я получаю следующий вывод...
running with a for loop...
arg #1 is 134.5, arg #2 is 232.45 at 11:58:17.025493
arg #1 is 213.38, arg #2 is 306.7 at 11:58:18.027038
arg #1 is 107.3, arg #2 is 347.19 at 11:58:19.028476
Running with itertools.starmap...
arg #1 is 167.7, arg #2 is 247.96 at 11:58:20.030238
arg #1 is 235.97, arg #2 is 318.02 at 11:58:21.031543
arg #1 is 140.41, arg #2 is 387.51 at 11:58:22.032727
Running with pathos.mp.starmap...
arg #1 is 120.24, arg #2 is 208.23 at 11:58:23.100251
arg #1 is 220.24, arg #2 is 308.23 at 11:58:23.112206
arg #1 is 120.24, arg #2 is 308.23 at 11:58:23.126050
Проблема в том, что когда я распараллеливаю это, случайные функции НЕ оцениваются каждый раз по-разному. Они оцениваются только один раз (или результат каким-то образом повторно используется снова и снова...), если вы посмотрите на последний блок, значения из переданных случайных функций не меняются. Я поставил туда временные метки, чтобы убедить себя, что последний блок действительно выполнялся параллельно.
Я уверен, что это как-то связано с тем, когда и как оцениваются параметры кортежа для вызовов функций, но в этот момент я потерялся.
Цель очень высокого уровня состоит в том, чтобы иметь возможность создать (очень большой) список параметров для передачи в среду simPy, и чтобы пул выполнялся на них параллельно. Но пока я не разобрался, как заставить работать случайность, я застрял, делая это на 1/32 скорости, которая мне нужна.
func1
иfunc2
вызываются внутриexample
, глобальный генератор случайных чисел создает значение, которое изменяет внутреннее состояние генератора.example
передаетсяstarmap
, аstarmap
потенциально может вызыватьexample
несколько раз одновременно. Еслиexample
вызывается несколько раз одновременно, у вас потенциально может быть несколько одновременных вызововfunc1
иfunc2
, что означает, что генератор случайных чисел управляется несколькими процессами одновременно. - person Carcigenicate   schedule 29.11.2019starmap
я имею в видуpool.starmap
, а неitertools
'starmap
. Версияitertools
не работает параллельно, так что все в порядке. - person Carcigenicate   schedule 29.11.2019example
числа из очереди. - person Carcigenicate   schedule 29.11.2019