2016-10-06 1 views
0

저는 멀티 프로세싱을 연구 중이며 웹 사이트에서이 예제를 사용했습니다. 그러나 내 MacBook 망에서이 예제를 실행하려고해도 아무런 변화가 없습니다. 다음은 예였다멀티 프로세싱을 사용할 때 process.join을 스크립트에 넣으면 파이썬이 충돌합니다.

그것은 내가 'list_append'기능으로 인쇄 문을 넣어 후에 나오는 것에 따라
import random 
import multiprocessing 


def list_append(count, id, out_list): 
""" 
Creates an empty list and then appends a 
random number to the list 'count' number 
of times. A CPU-heavy operation! 
""" 
for i in range(count): 
    out_list.append(random.random()) 

if __name__ == "__main__": 
size = 10000000 # Number of random numbers to add 
procs = 2 # Number of processes to create 

# Create a list of jobs and then iterate through 
# the number of processes appending each process to 
# the job list 
jobs = [] 
for i in range(0, procs): 
    out_list = list() 
    process = multiprocessing.Process(target=list_append, 
     args=(size, i, out_list)) 
    jobs.append(process) 

# Start the processes (i.e. calculate the random number lists)  
for j in jobs: 
    j.start() 

# Ensure all of the processes have finished 
for j in jobs: 
j.join() 

print ("List processing complete.") 

는, 아무것도 인쇄하지 않기 때문에 문제는 실제로 j.join() 오히려 j.start() 비트 아닙니다.

+0

왜 프로세스를 생성, 시작 및 결합하는 데 별도의 루프가 있습니까? – corn3lius

+0

@ Corn3lius - 필자는 온라인에서 찾은 예제에서 문자 그대로 복사하여 붙여 넣었지만 그렇지 않은 경우에는 루프에서 빼내려고했습니다. 그러나 똑같은 문제가 발생했습니다. –

답변

0

multiprocessing.Process으로 프로세스를 생성 할 때 다른 프로세스에서 비동기 적으로 실행될 하위 함수를 준비하십시오. start 메서드를 호출하면 계산이 시작됩니다. 조인 메소드는 계산이 완료 될 때까지 대기합니다. 따라서 프로세스를 시작하고 완료 될 때까지 기다리지 (또는 join) 않으면 프로그램이 종료 될 때 프로세스가 종료되므로 아무 일도 일어나지 않습니다.

여기서 한 가지 문제는 multiprocessing에서 공유 할 수있는 개체를 사용하고 있지 않다는 것입니다. 공통적 인 list()을 사용할 때 각 프로세스는 메모리의 다른 목록을 사용합니다. 프로세스가 종료되고 기본 목록이 비어지면 로컬 프로세스가 지워집니다. 제대로 out_queue에 다시 전송 결과의 수를 계산하지 않는 경우이 코드는 아주 쉽게 걸 수

import random 
import multiprocessing 


def list_append(count, id, out_queue): 
    """ 
    Creates an empty list and then appends a 
    random number to the list 'count' number 
    of times. A CPU-heavy operation! 
    """ 
    for i in range(count): 
     out_queue.put((id, random.random())) 

if __name__ == "__main__": 
    size = 10000 # Number of random numbers to add 
    procs = 2 # Number of processes to create 

    # Create a list of jobs and then iterate through 
    # the number of processes appending each process to 
    # the job list 
    jobs = [] 
    q = multiprocessing.Queue() 
    for i in range(0, procs): 
     process = multiprocessing.Process(target=list_append, 
              args=(size, i, q)) 
     process.start() 
     jobs.append(process) 

    result = [] 
    for k in range(procs*size): 
     result += [q.get()] 

    # Wait for all the processes to finish 
    for j in jobs: 
     j.join() 

    print("List processing complete. {}".format(result)) 

주 : 당신은 당신이 multiprocessing.Queue를 사용해야 데이터 간의 프로세스를 교환 할 수 있도록합니다.
너무 많은 결과를 검색하려고 시도하면 q.get은 절대 나오지 않을 추가 결과를 기다립니다. q에서 모든 결과를 검색하지 않으면 out_queue이 꽉 차서 프로세스가 중단되고 out_queue.put이 반환되지 않습니다. 따라서 프로세스가 종료되지 않으므로 프로세스에 참여할 수 없습니다.
계산이 독립적 인 경우 Pool과 같은 상위 수준 도구 또는 joblib과 같은 훨씬 강력한 타사 라이브러리를 살펴 보는 것이 좋습니다. (see this answer for some insights on Process vs Pool/joblib)

Queue에 많은 개체를 넣으려고하면 프로그램이 느려지므로 실제로 숫자 size이 줄어 들었습니다. 작은 객체를 많이 전달해야하는 경우 모든 객체를 하나의 일괄 처리로 전달하십시오.

import random 
import multiprocessing 


def list_append(count, id, out_queue): 
    a = [random.random() for i in range(count)] 
    out_queue.put((id, a)) 

if __name__ == "__main__": 
    size = 10000 # Number of random numbers to add 
    procs = 2 # Number of processes to create 
    jobs = [] 
    q = multiprocessing.Queue() 
    for i in range(0, procs): 
     process = multiprocessing.Process(target=list_append, 
              args=(size, i, q)) 
     process.start() 
     jobs.append(process) 
    result += [q.get() for _ in range(procs)] 
    for j in jobs: 
     j.join() 
    print("List processing complete.") 
+0

첫 번째 프로그램에서'j.join()'다음에 작은 print 문을 추가했고 IDLE 인쇄없이 지난 20 분 동안 아무런 아이디어가 없습니다. –

+0

이 코드는 코드가 영원히 걸릴 수있는 somme 교착 상태의 영향을받습니다. 큐에서 올바른 양의 결과를 검색해야합니다 (검색하려고 시도하면 더 많이 멈 춥니 다). 대기열에서 충분한 결과를 검색하지 못하면 대기열이 Full이 될 수 있으며 프로세스가 종료되지 않도록 할 수 있습니다. 디버깅을 위해'result + = [q.get()]'및'out_queue.put ((id, random.random()))'다음에 print 문을 사용하여 yoru 프로그램에서 무엇이 정지되는지 확인할 수 있습니다. –

+0

'result + = [q.get()]'과'out_queue.put ((id, random.random()))'다음에 print 문을 넣었지만 아무 것도 IDLE에 출력하지 않았습니다. –

관련 문제