Python многопроцессорно работает с несколькими входами
В Python модуль multiprocessing
может использоваться для параллельной работы функции над диапазоном значений. Например, это дает список первых 100000 оценок f.
def f(i):
return i * i
def main():
import multiprocessing
pool = multiprocessing.Pool(2)
ans = pool.map(f, range(100000))
return ans
Можно ли сделать подобное, если f принимает несколько входов, но меняется только одна переменная? Например, как бы вы распараллеливали это:
def f(i, n):
return i * i + 2*n
def main():
ans = []
for i in range(100000):
ans.append(f(i, 20))
return ans
Ответы
Ответ 1
Есть несколько способов сделать это. В примере, указанном в вопросе, вы можете просто определить функцию-обертку
def g(i):
return f(i, 20)
и передать эту оболочку на map()
. Более общий подход состоит в том, чтобы иметь оболочку, которая принимает один аргумент кортежа и распаковывает кортеж в несколько аргументов
def g(tup):
return f(*tup)
или используйте эквивалентное лямбда-выражение: lambda tup: f(*tup)
.
Ответ 2
Вы можете использовать functools.partial
def f(i, n):
return i * i + 2*n
def main():
import multiprocessing
pool = multiprocessing.Pool(2)
ans = pool.map(functools.partial(f, n=20), range(100000))
return ans
Ответ 3
Если вы используете мою вилку multiprocessing
, называемую pathos
, вы можете получить пулы, которые принимают несколько аргументов... а также принимают функции lambda
. Самое приятное в том, что вам не нужно изменять свои конструкторы программирования, чтобы они работали параллельно.
>>> def f(i, n):
... return i * i + 2*n
...
>>> from itertools import repeat
>>> N = 10000
>>>
>>> from pathos.pools import ProcessPool as Pool
>>> pool = Pool()
>>>
>>> ans = pool.map(f, xrange(1000), repeat(20))
>>> ans[:10]
[40, 41, 44, 49, 56, 65, 76, 89, 104, 121]
>>>
>>> # this also works
>>> ans = pool.map(lambda x: f(x, 20), xrange(1000))
>>> ans[:10]
[40, 41, 44, 49, 56, 65, 76, 89, 104, 121]
Ответ 4
Вы можете использовать бедный человек, каррирующий (он же оберните его):
new_f = lambda x: f(x, 20)
затем вызовите new_f(i)
.