2009-07-25 3 views
24

저는 파이썬의 multiprocessing module에 대해 읽었습니다. 나는 아직도 내가 할 수있는 일에 대해 아주 잘 이해하고 있다고 생각하지 않는다.파이썬 : 멀티 코어 프로세싱?

쿼드 코어 프로세서가 있고 1,000,000 개의 정수가있는 목록이 있고 모든 정수의 합이 필요하다고 가정 해 봅시다. 간단히 할 수 있습니다 :

list_sum = sum(my_list) 

그러나 이것은 하나의 코어에만 보냅니다.

다중 처리 모듈을 사용하여 배열을 나눌 수 있으며 각 코어가 합계를 구하여 합계를 계산할 수 있도록 값을 반환 할 수 있습니까? 같은

뭔가 : 어떤 도움을 주시면 감사하겠습니다

core1_sum = sum(my_list[0:500000])   #goes to core 1 
core2_sum = sum(my_list[500001:1000000]) #goes to core 2 
all_core_sum = core1_sum + core2_sum  #core 3 does final computation 

.

답변

30

예, 그것은 매우 여러 스레드와 함께 그 일을 같이 여러 프로세스를 통해이 요약 할 수있다 : 그러나

from multiprocessing import Process, Queue 

def do_sum(q,l): 
    q.put(sum(l)) 

def main(): 
    my_list = range(1000000) 

    q = Queue() 

    p1 = Process(target=do_sum, args=(q,my_list[:500000])) 
    p2 = Process(target=do_sum, args=(q,my_list[500000:])) 
    p1.start() 
    p2.start() 
    r1 = q.get() 
    r2 = q.get() 
    print r1+r2 

if __name__=='__main__': 
    main() 

, 여러 프로세스를 사용하여 작업하는 것이 단일 프로세스에서 수행하는 것보다 느릴 수 있습니다. 데이터를 앞뒤로 복사하는 것이 즉시 합산하는 것보다 비용이 많이 듭니다.

+1

@Martin, http://docs.python.org/library/multiprocessing.html#multiprocessing-programming에 따라이 교착 상태가 발생한다고 생각합니다. 대기열은 모든 버퍼링 된 항목이 "피더"스레드에 의해 기본 파이프로 공급 될 때까지 종료 될 것입니다. "- 교착 상태가 발생하는 예제는 코드와 매우 유사합니다 (시작, 결합, get의 단일 하위 프로세스입니다. 시퀀스)와 하나가 아닌 두 개의 하위 프로세스가 도움이되지 않습니다. 조인을 바꾸고 가져 오거나 조인을 제거하십시오. –

+0

"그것은 나를 위해 일했습니다"아마도 데이터가 단순히 파이프에 맞기 때문입니다. 어떤 경우이든 조인을 제거했습니다. –

+0

Linux에서 이것을 실행하고 있습니까? – Nope

20

동시 프로그래밍의 세계에 오신 것을 환영합니다.

파이썬이 할 수있는 일 (그리고 할 수없는 일)은 두 가지에 달려 있습니다.

  1. OS가 수행 할 수있는 작업 (수행 할 수없는 작업) 대부분의 OS는 코어에 프로세스를 할당합니다. 4 개의 코어를 사용하려면 문제를 4 가지 프로세스로 분리해야합니다. 이것은 소리보다 쉽습니다. 때때로.

  2. 기본 C 라이브러리가 수행 할 수있는 작업 (수행 할 수없는 작업) C 라이브러리가 OS의 기능을 드러내고 OS가 하드웨어의 기능을 드러내는 경우, 당신은 확실합니다.

여러 프로세스, 특히 GNU/Linux에서 문제를 해결하려면 쉽습니다. 이를 다중 단계 파이프 라인으로 분해하십시오.

백만 개의 숫자를 합산하는 경우 다음 쉘 스크립트를 생각해보십시오. 숫자의 범위 또는 표준 입력의 숫자 목록을 합친 가정을 가정합니다. sum.py

(sum.py 0 500000 & sum.py 50000 1000000) | sum.py

3 개의 동시 프로세스가 있습니다. 두 개는 많은 수의 합계를, 세 번째는 두 개의 수를 합한 것입니다.

GNU/Linux 셸과 OS가 이미 동시성의 일부를 처리하기 때문에 stdin에서 읽고 stdout에 쓰고 작은 부분을 처리하도록 설계된 간단한 (매우 간단한) 프로그램을 설계 할 수 있습니다. 큰 직업.

subprocess을 사용하여 작업을 셸에 할당하는 대신 파이프 라인을 빌드하여 오버 헤드를 줄이려고 할 수 있습니다. 그러나 쉘이 매우 빠르게 파이프 라인을 빌드한다는 것을 알 수 있습니다. (. 그것은 C에 직접 기록하고 당신을 위해 직접 OS API 호출을하게되었다)

+0

나는이 대답이 많은 독창성을 보였다 고 느꼈다. 간접 참조 계층을 추가하는 것만으로 CS에서의 문제를 해결할 수 없습니다. – earino

+0

@earino : OTOH, OP의 질문에 전혀 답을 얻지 못했습니다.이 질문은 "다중 처리 모듈을 어떻게 사용합니까"에 관한 것입니다. –

+2

@ Martin v. Löwis : 참. IMO보다 큰 문제 (모든 코어 사용)는 질문 (모든 코어를 사용하기 위해 하위 프로세스 사용)보다 중요한 경우가 많습니다. 어떤 경우에는 질문이 가난한 가정의 숫자를 반영 질문했다. –

7

은 물론, 예를 들면 다음과 같습니다에

from multiprocessing import Process, Queue 

thelist = range(1000*1000) 

def f(q, sublist): 
    q.put(sum(sublist)) 

def main(): 
    start = 0 
    chunk = 500*1000 
    queue = Queue() 
    NP = 0 
    subprocesses = [] 
    while start < len(thelist): 
     p = Process(target=f, args=(queue, thelist[start:start+chunk])) 
     NP += 1 
     print 'delegated %s:%s to subprocess %s' % (start, start+chunk, NP) 
     p.start() 
     start += chunk 
     subprocesses.append(p) 
    total = 0 
    for i in range(NP): 
     total += queue.get() 
    print "total is", total, '=', sum(thelist) 
    while subprocesses: 
     subprocesses.pop().join() 

if __name__ == '__main__': 
    main() 

결과 :이 단위가에 대한 가치가 산란 프로세스로 너무 좋은 것을

$ python2.6 mup.py 
delegated 0:500000 to subprocess 1 
delegated 500000:1000000 to subprocess 2 
total is 499999500000 = 499999500000 

참고 - 전체 합산 작업은 인 (작 왜 내가 주 체크에서 합계를 다시 계산할 수 있나 ;-) 너무 많은 데이터가 앞뒤로 움직이고있다. (실제로 서브 프로세스는 작업하는 서브리스트의 복사본을 얻을 필요가 없다 - 인덱스만으로 충분할 것이다). 따라서 멀티 프로세싱이 실제로 보장되지 않는 "장난감 예제"입니다. 다른 아키텍처 (대기열에서 수행 할 여러 작업을받는 하위 프로세스 풀 사용, 앞뒤로의 데이터 이동 최소화 등) 및 덜 세분화 된 작업에서는 실제로 성능면에서 이점을 얻을 수 있습니다.