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).