w2_sharing_queue - steelbear/HMG_Softeer_DE GitHub Wiki

멀티 프로세싱 환경에서 Queue 공유하기

멀티 프로세싱에서 중요한 부분 중 하나는 프로세스 간 데이터 공유가 올바르게 이루어져야 한다. 파이썬의 경우에도 multiprocessing 라이브러리릉 통해 자식 프로세스를 생성하고 데이터 공유를 할 수 있도록 다양한 클래스와 함수를 지원한다. 하지만 multiprocessing.Queue를 무작정 공유하게 되면 다음과 같은 문제가 발생한다.

from multiprocessing import Queue, Pool

if __name__ == '__main__':
    tasks_to_accomplish = Queue()
    tasks_that_are_done = Queue()

    for i in range(10):
        tasks_to_accomplish.put(i)
        print(f"Task no {str(i)}")

    with Pool(4) as p:
        p.starmap(work, [(i, tasks_to_accomplish, tasks_that_are_done) for i in range(4)])

| RuntimeError: Queue objects should only be shared between processes through inheritance

간단히 말하자면, 데이터를 공유하는 객체에 자식 프로세스가 직접 접근하면 안된다는 뜻이다. 이를 위해 우리는 Manager를 사용해야 한다.

from multiprocessing import Manager, Pool

if __name__ == '__main__':
    with Manager() as manager:
        tasks_to_accomplish = manager.Queue()
        tasks_that_are_done = manager.Queue()

        for i in range(10):
            tasks_to_accomplish.put(i)
            print(f"Task no {str(i)}")

        with Pool(NUM_WORKERS) as p:
            p.starmap(work, [(i, tasks_to_accomplish, tasks_that_are_done) for i in range(NUM_WORKERS)])

다음과 같이 하면 manager.Queue()를 통해 공유 메모리 객체를 생성할 수 있다. 다만 직접 multiprocessing.Queue를 인스턴스화하는 것과는 달리, 원본 객체에 요청을 넣을 수 있는 프록시(Proxy) 객체가 나오게 된다. 이를 통해 각 자식프로세스는 직접 공유 메모리 객체에 접근하지 않고 공유 데이터를 읽고 쓸 수 있다.

Reference