Как передать * аргументы пафосу

У меня следующая проблема: я хотел бы использовать amap от pathos.multiprocessing.

import pathos as pt

class Foo:

    def __init__(self):
        pass

    def f(self, a, b, c):
        return a + b + c

    def g(self):  
        pool = pt.multiprocessing.ProcessPool()
        def _h(a, b, c):
            k = self.f(a, b, c)
            return k/2
        result = [pool.amap(_h, (i, j, k)) for i in range(3) for j in range(5) for k in range(7)]
        return result

a = Foo()
b = a.g()
b[0].get()

Необходимо иметь эти две функции f и g, хотя я мог бы делать все в пределах f.

Если я запускаю этот код, я получаю, что g ожидает 3 аргумента, но один был дан.

TypeError: _h() takes exactly 3 arguments (1 given)

Как я могу это исправить?

2 ответа

Решение

Так как amap определяется как:

149     def amap(self, f, *args, **kwds): # register a callback ?
...
152         return _pool.map_async(star(f), zip(*args)) # chunksize

в исходном коде есть пример использования:

pool.amap(pow, [1,2,3,4], [5,6,7,8])

дано l как ваш вклад:

l = [(i, j, k) for i in range(3) for j in range(5) for k in range(7)]

Вы можете перенести свой вклад:

results = pool.amap(_h, *map(list, zip(*l)))

или используйте генератор, который должен быть быстрее:

def getter(n):
    for e in l:
        yield e[n]
result = pool.amap(_h, *[getter(n) for n in range(3)])

или использовать apipe API вместо этого:

results = [pool.apipe(_h, l)]

конечно, вы можете сделать ввод более подходящим с его интерфейсом, как только у вас появится идея. но почему бы просто не использовать multiprocessing.pool.async_apply вместо этого его интерфейс в точности соответствует тому, что вы ожидали сначала.

Я знаю, это выглядит странно, однако мне нравится идея передавать данные как итеративные в пафосе.

Чтобы достичь того, что вы ищете, вы должны передать элементы как отдельный повторяемый элемент. Вот пример:

def g(self):  
    pool = pt.multiprocessing.ProcessPool()
    def _h(a, b, c):
        k = self.f(a, b, c)
        return k/2
    result = [pool.amap(_h, (i,),( j,),(k,))) for i in range(3) for j in range(5) for k in range(7)]
    return result

Пожалуйста, обратите внимание на странный способ передачи параметров здесь: pool.amap(_h, (i,),( j,),(k,))

Вы можете понять, почему это так, если вы отследите вызов _pool.map_async(star(f), zip(*args)).

В общем, вы можете вызывать вашу функцию несколько раз с разными параметрами. Вот что я сделал, чтобы продемонстрировать это:

def g(self):  
    pool = pt.multiprocessing.ProcessPool()
    def _h(a, b, c):
        print('a: {0} b: {1}. c: {2}'.format(a, b, c))
        k = self.f(a, b, c)
        return k/2
    return [pool.amap(_h, (1,4), (2,5), (3,6))]

Даже когда я вызывал функцию один раз, она выполнялась дважды. Выход:

a: 1 b: 2. c: 3
a: 4 b: 5. c: 6

Надеюсь это поможет.

Другие вопросы по тегам