2014-08-28 11 views
29

하나 이상의 매개 변수를 허용하는 pool.map() 함수를 사용하려면 몇 가지 방법이 필요합니다. 내 이해에 따라 pool.map()의 대상 함수는 하나의 매개 변수로만 반복 가능하지만 다른 매개 변수도 전달할 수있는 방법이 있습니까? 이 경우 필자는 Lock() 및 대상 정보에 대한 로깅 정보와 같은 몇 가지 구성 변수를 전달해야합니다.여러 매개 변수를 Python의 pool.map() 함수에 전달

몇 가지 연구를 해본 결과 일부 기능을 사용할 수 있다고 생각합니다. 그러나 나는 이것이 어떻게 작동하는지 완전히 이해하지 못합니다. 어떤 도움이라도 대단히 감사하겠습니다! 여기에 내가 뭘 원하는지의 간단한 예는 다음과 같습니다

def target(items, lock): 
    for item in items: 
     # Do cool stuff 
     if (... some condition here ...): 
      lock.acquire() 
      # Write to stdout or logfile, etc. 
      lock.release() 

def main(): 
    iterable = [1, 2, 3, 4, 5] 
    pool = multiprocessing.Pool() 
    pool.map(target(PASS PARAMS HERE), iterable) 
    pool.close() 
    pool.join() 
+0

여기에 설명 : Python multiprocessing pool.map for multiple arguments

여기 pathos가하기 (영업의 게시물에 코멘트에 @Roberto에 의해 언급) : 여기에 본 그 경우에 가장 좋은 방법은 multiprocessing.starmap을 사용하는 것입니다 http://stackoverflow.com// 다중 인스턴스를위한 파이썬 멀티 프로세싱 - pool-map-for-multiple-arguments (JF Sebastien의 "star"메소드를 성공적으로 사용했습니다) – Roberto

+1

다중 처리를 사용할 때마다 close/join과 함께 try/finally 절을 사용하십시오.()를 호출하여 오류가 발생하면 프로세스가 닫히도록합니다. http://stackoverflow.com/questions/30506489/python-multiprocessing-leading-to-many-zombie-processes – zeehio

답변

49

(당신이 의심으로) 당신은이에 대한 functools.partial를 사용할 수 있습니다

from functools import partial 

def target(lock, iterable_item): 
    for item in iterable_item: 
     # Do cool stuff 
     if (... some condition here ...): 
      lock.acquire() 
      # Write to stdout or logfile, etc. 
      lock.release() 

def main(): 
    iterable = [1, 2, 3, 4, 5] 
    pool = multiprocessing.Pool() 
    l = multiprocessing.Lock() 
    func = partial(target, l) 
    pool.map(func, iterable) 
    pool.close() 
    pool.join() 

예 :

def f(a, b, c): 
    print("{} {} {}".format(a, b, c)) 

def main(): 
    iterable = [1, 2, 3, 4, 5] 
    pool = multiprocessing.Pool() 
    a = "hi" 
    b = "there" 
    func = partial(f, a, b) 
    pool.map(func, iterable) 
    pool.close() 
    pool.join() 

if __name__ == "__main__": 
    main() 

출력 :

hi there 1 
hi there 2 
hi there 3 
hi there 4 
hi there 5 
+0

굉장, 나는 내가 필요한 모든 것이 이것과 같은 명확한 예라고 생각한다. 엄청 고마워! – DJMcCarthy12

+0

좋은 예입니다. 하나의 질문 : 왜'item에있는 항목 :'이'target'의 정의에 있습니까? –

+0

@ Jean-FrancoisT. 복사/붙여 넣기 실수! 그것을 지적 주셔서 감사합니다. – dano

0

당신이 functools.partial에 접근 할 수없는 경우에는 이것을위한 래퍼 함수를 ​​사용할 수도 있습니다.

def target(lock): 
    def wrapped_func(items): 
     for item in items: 
      # Do cool stuff 
      if (... some condition here ...): 
       lock.acquire() 
       # Write to stdout or logfile, etc. 
       lock.release() 
    return wrapped_func 

def main(): 
    iterable = [1, 2, 3, 4, 5] 
    pool = multiprocessing.Pool() 
    lck = multiprocessing.Lock() 
    pool.map(target(lck), iterable) 
    pool.close() 
    pool.join() 

이 잠금을 허용하는 기능으로 target()하게 (또는 당신이주고 싶은 파라미터 무엇이든), 그리고 그것은 단지 입력으로 반복 가능한에서받는 함수를 반환합니다,하지만 여전히 다른 모든 매개 변수를 사용할 수 있습니다 . 이것이 궁극적으로 pool.map()으로 전달되는데 문제없이 실행되어야합니다.

+1

나는 이것에 아주 늦었지만, 중첩 된 함수는 절이 수 없기 때문에이 코드는 작동하지 않을 것이다. 'target (lck) '을 호출하면 중첩 된'wrapped_func' 함수가 반환됩니다.이 함수는 작업자 프로세스에 전달하기 위해 절이되어야하며 항상 실패합니다. – dano

3

multiprocessing의 포크가 pathos에있는 것처럼 여러 인수를 허용하는 맵 함수를 사용할 수 있습니다.

>>> from pathos.multiprocessing import ProcessingPool as Pool 
>>> 
>>> def add_and_subtract(x,y): 
... return x+y, x-y 
... 
>>> res = Pool().map(add_and_subtract, range(0,20,2), range(-5,5,1)) 
>>> res 
[(-5, 5), (-2, 6), (1, 7), (4, 8), (7, 9), (10, 10), (13, 11), (16, 12), (19, 13), (22, 14)] 
>>> Pool().map(add_and_subtract, *zip(*res)) 
[(0, -10), (4, -8), (8, -6), (12, -4), (16, -2), (20, 0), (24, 2), (28, 4), (32, 6), (36, 8)] 

pathos

여러 입력하면 쉽게 둥지 계층 병렬지도를 할 수 있습니다, 그래서 우리는 그것을 설명하기 위해 예를 확장 할 수 있습니다.

>>> from pathos.multiprocessing import ThreadingPool as TPool 
>>> 
>>> res = TPool().amap(add_and_subtract, *zip(*Pool().map(add_and_subtract, range(0,20,2), range(-5,5,1)))) 
>>> res.get() 
[(0, -10), (4, -8), (8, -6), (12, -4), (16, -2), (20, 0), (24, 2), (28, 4), (32, 6), (36, 8)] 

더 재미있는 것은 우리가 풀에 전달할 수있는 중첩 기능을 만드는 것입니다. pathosdill을 사용하므로 파이썬에서 거의 모든 것을 직렬화 할 수 있기 때문에 가능합니다.

>>> def build_fun_things(f, g): 
... def do_fun_things(x, y): 
...  return f(x,y), g(x,y) 
... return do_fun_things 
... 
>>> def add(x,y): 
... return x+y 
... 
>>> def sub(x,y): 
... return x-y 
... 
>>> neato = build_fun_things(add, sub) 
>>> 
>>> res = TPool().imap(neato, *zip(*Pool().map(neato, range(0,20,2), range(-5,5,1)))) 
>>> list(res) 
[(0, -10), (4, -8), (8, -6), (12, -4), (16, -2), (20, 0), (24, 2), (28, 4), (32, 6), (36, 8)] 

표준 라이브러리 외부로 갈 수없는 경우에는 다른 방법으로해야합니다. https://github.com/uqfoundation

관련 문제