2017-04-14 1 views
2

클래스의 인스턴스가 여러 개 있으며 메서드를 호출하여 각 인스턴스를 수정하고 싶습니다. 그러나이 메서드는 반환하는 데 시간이 걸리는 시스템 명령을 호출하므로 몇 가지를 병렬로 수행하고 싶습니다. 나는 이것이 매우 간단한 일이 될 것이라고 생각했지만 나는 곤란을 겪었다.개체 수정을위한 메서드 호출 병렬 처리

import os 

class SquareMe(): 
    def __init__(self, x): 
     self.val = x 
    def square(self): 
     os.system('sleep 10') # I'll call a slow program 
     self.val = self.val **2 

if __name__ == '__main__': 
    objs = [SquareMe(x) for x in range(4)] 
    for obj in objs: 
     obj.square() # this is where I want to parallelize it 
    print([obj.val for obj in objs]) 

이 코드는 작동합니다 (인쇄 [0, 1, 4, 9),하지만 그것을 실행하는 데 40 초 소요 : 여기에 내가 달성하고 싶은 유사 예이다. 나는 그것을 대략 10 초까지 내려고 노력하고있다.

저는 서브 프로세스와 멀티 프로세싱 모듈을 살펴 봤지만, 이해할 수 있도록 square()를 평가하기 전에 객체를 pickle합니다. 즉, 각 객체의 복사본이 수정되고 원본은 그대로 유지됩니다. 나는 해결책이 자기를 돌려주고 원문을 덮어 씌울 것이라고 생각했다. 그러나 그것이 가능하다면 그것은 그다지 간단하지 않다. 나는 스레딩을 들여다 보면서 나는 거기에서 같은 문제를 겪을 것이라는 인상을 받았다.

나는 또한 async (나는 파이썬 3.5를 사용하고있다)를 사용하는 방법을 살펴 보았다. 내가 말할 수있는 것부터, 시스템 호출 ('sleep 10'포함)이 블로킹 중이므로 비동기가 속도를 높이지 못한다.

이렇게 간단하고 우아하고 파이썬 적 방법이 있습니까?

+0

당신이 트위스트 (https://twistedmatrix.com/trac/)하지만 반드시 그렇게 대답으로 게시하지하고 있지 않다있는 실행 가능한 해결책을 찾을 수있는 기대 : 여기에 결국거야. –

+0

필자는 필자가 종종 GIL에 의해 곤란을 겪었 기 때문에이 질문을 따르게 될 것입니다. 사실 Python과 Windows를 실행하면 포크가 허용되지 않습니다. 물론 객체가 다중 처리로 투명하게 처리된다는 사실도 마찬가지입니다. 다중 처리 및 공유 numpy 배열의 문제점에 대해 저를 시작하지 마십시오. 계산 집약적 인 작업을 할 때 종종 Cython으로 가야합니다. 개방형 MP를 통해 다중 프로세스를 수행 할 수 있습니다. –

+0

개체 수정을 두 부분으로 나눌 수 있습니다. 하나는 비싸지 만 개체에 단단히 묶일 필요는 없습니다 (예 : 외부 코드 호출). 그리고 저렴한 개체와 실제 개체 변경 ? 만약 그렇다면, 당신은 아마도'멀티 프로세싱 '으로 값 비싼 부분을 병렬화하고 메인 프로세스에서 더 값싼 부분만을 유지할 수 있습니다. 객체의 데이터를 업데이트하거나 외부 코드에 대한 인수를 추출하는 것이 값 비싼 부분이기 때문에 부품을 분리하는 쉬운 방법이 없다면 좋은 해결책이 없다고 생각합니다. – Blckknght

답변

0

올바른 코드를 찾으면 멀티 프로세싱과 '자기 복귀'를 사용하는 것이 매우 간단합니다.

import os 
import multiprocessing 

class SquareMe(): 
    def __init__(self, x): 
     self.val = x 
    def square(self): 
     os.system('sleep 10') # I'll call another program, which take a while 
     self.val = self.val **2 
     return self 

if __name__ == '__main__': 
    objs = [SquareMe(x) for x in range(4)] 
    pool = multiprocessing.Pool(4) 
    objs = pool.map(SquareMe.square, objs) 
    pool.close() 
    pool.join() 
    print([obj.val for obj in objs]) 
+0

코드에서 ** _ pickle.PicklingError : 피클링을 수행 할 수 없습니다 : __main__에서 속성 조회가 실패했습니다 ** – stovfl