2013-11-27 2 views
0

나는 서로 독립적으로 해결되는 일련의 작업으로 구성된 난처하게 병렬화 가능한 문제를 가지고 있습니다. 각각의 작업을 해결하는 것은 꽤 길기 때문에 다중 처리의 주요 후보자입니다.파이썬 프로세스에서 객체 생성 및 재사용

문제는 내 작업을 해결하려면 자체적으로 시간이 많이 걸리지 만 모든 작업에 다시 사용할 수있는 특정 개체를 만들어야한다는 것입니다 (시작할 필요가있는 외부 바이너리 프로그램을 생각해보십시오). 따라서 직렬 내가 멀티를 사용하여이 프로그램을 병렬화 할 때 my_object는 절인 할 수 없습니다 (이유에 대한 매개 변수로 전달 될 수 없습니다

def costly_function(task, my_object): 
    solution = solve_task_using_my_object 
    return solution 

def solve_problem(): 
    my_object = create_costly_object() 
    tasks = get_list_of_tasks() 
    all_solutions = [costly_function(task, my_object) for task in tasks] 
    return all_solutions 

더 이상 실행하지 않아야 버전이 같은 일을 할 작업 동시에), 그래서 각 작업에 대한 개체의 별도 인스턴스를 만드는 리조트해야합니다 :

def costly_function(task): 
    my_object = create_costly_object() 
    solution = solve_task_using_my_object 
    return solution 

def psolve_problem(): 
    pool = multiprocessing.Pool() 
    tasks = get_list_of_tasks() 
    all_solutions = pool.map_async(costly_function, tasks) 
    return all_solutions.get() 

이지만 복수 인스턴스를 작성하면 추가 비용이 my_object이되므로이 코드는 직렬화 된 것보다 약간 더 빠릅니다.

각 프로세스에 my_object이라는 별도 인스턴스를 만든 다음 해당 프로세스에서 실행되는 모든 작업에 대해 다시 사용할 수 있으면 내 타이밍이 크게 향상됩니다. 어떻게해야하는지에 대한 모든 포인터?

답변

3

표준 라이브러리 이외의 도구를 가져 오지 않고도 내 자신의 문제를 해결할 수있는 간단한 방법을 찾았습니다. 비슷한 문제가있는 경우에 대비하여 여기에 적어 두었습니다.

multiprocessing.Pool은 각 프로세스가 시작될 때 실행되는 initializer 함수 (인수 포함)를 허용합니다. 이 함수의 반환 값은 어디에도 저장되지 않고, 하나는 글로벌 변수 설정 기능을 활용할 수 있습니다 : 각 프로세스는 별도의 글로벌 네임 스페이스를 가지고 있기 때문에

def init_process(): 
    global my_object 
    my_object = create_costly_object() 

def costly_function(task): 
    global my_object 
    solution = solve_task_using_my_object 
    return solution 

def psolve_problem(): 
    pool = multiprocessing.Pool(initializer=init_process) 
    tasks = get_list_of_tasks() 
    all_solutions = pool.map_async(costly_function, tasks) 
    return all_solutions.get() 

는, 인스턴스화 된 객체가 충돌하지 않는, 그리고 프로세스마다 한 번만 생성됩니다.

아마도 가장 우아한 해결책은 아니지만 간단하고 충분히 빠른 속도를 제공합니다.

1

당신은 또한 모든 작업에 의해 후자 사용할 수있는 몇 가지 작업 initialization를 실행할 수있는 방법이 celery project이 많은 다른 기능들, 당신을 위해 모든 것을 처리 할 수 ​​있습니다

+0

감사합니다. 샐러리가 멋지지만 내 목적을 위해 과도한 잔인 함, 메시징을위한 별도의 중개인 및 전체 앱 상용구가 저에게 과도한 비트입니다 ... – Javier

1

당신은 객체를 pickable하도록 제한되어 옳다 multiprocessing을 사용할 때 당신은 당신의 물건이 피 피할 수 없다는 것을 절대 확신합니까?

dill을 사용해 보셨습니까? 그것을 가져 오면 피클을 호출 할 때마다 딜 바인딩을 사용합니다. sympy 방정식에서 다중 처리를 사용하려고 할 때 저에게 효과적이었습니다.

+0

내 물건을 피클해도 하드, 파이썬 인터프리터 외부에서 실행되는 시스템 바이너리 포함), 작업을 완료하기 위해 지속적 상태를 유지해야한다. 동일한 객체를 동시에 실행되는 두 개의 서로 다른 작업에 전달하는 경우 해당 상태를 덮어 쓰거나 객체 차단 (다중 처리의 목적을 상실한)을 사용해야합니다. – Javier