본문 바로가기

프로그래밍 언어/파이썬

파이썬 멀티프로세싱 라이브러리 프로세스, 큐, 풀 사용법

파이썬 멀티프로세싱 라이브러리 프로세스, 큐, 풀 사용법

파이썬에서 병렬 처리를 효율적으로 수행하기 위해 멀티프로세싱(multiprocessing) 라이브러리를 사용합니다. 이 라이브러리는 여러 프로세스를 생성하고 관리하여 CPU의 여러 코어를 활용할 수 있게 해줍니다. 이 글에서는 멀티프로세싱의 기본 개념부터 Process, Queue, Pool과 같은 주요 구성 요소를 이해하고, 실제 코드에서 어떻게 적용할 수 있는지를 알아보겠습니다.

 

 

목차

  1. 멀티프로세싱이란?
  2. 멀티프로세싱의 필요성
  3. Process 클래스
  4. Queue 클래스
  5. Pool 클래스
  6. 멀티프로세싱 활용 시 주의사항
  7. 실전 예제: 멀티프로세싱을 활용한 데이터 처리

 

멀티프로세싱이란?

멀티프로세싱은 여러 프로세스를 동시에 실행하여 작업을 병렬로 처리하는 기법입니다. 이 방식은 주로 CPU 바운드 작업에서 성능 향상을 위해 사용됩니다. 파이썬의 multiprocessing 라이브러리는 멀티스레딩의 GIL(Global Interpreter Lock) 문제를 해결하기 위해 설계되어, 프로세스 간 독립적인 메모리 공간을 활용해 안전하게 병렬 처리를 수행할 수 있습니다.

멀티프로세싱의 필요성

파이썬에서는 멀티스레딩을 사용할 때 GIL로 인해 CPU 코어를 효율적으로 사용하지 못하는 문제가 발생합니다. 멀티프로세싱은 이러한 문제를 해결해 각 프로세스가 별도의 메모리 공간에서 독립적으로 실행되도록 합니다. 이를 통해 CPU 코어를 최대한 활용할 수 있으며, 대규모 데이터 처리나 복잡한 연산 작업에서 유리합니다.

 

 

Process 클래스

Process 클래스는 새로운 프로세스를 생성하는 데 사용됩니다. 프로세스는 독립적인 메모리 공간을 가지며, 부모 프로세스의 자원을 공유하지 않습니다. Process 클래스를 사용하여 새로운 프로세스를 생성하고, 시작 및 종료를 관리할 수 있습니다.

from multiprocessing import Process

def worker():
    print("프로세스가 실행 중입니다.")

if __name__ == "__main__":
    p = Process(target=worker)
    p.start()
    p.join()  # 프로세스가 종료될 때까지 기다림

위 코드에서 Process 객체를 생성하고, start() 메서드를 호출하여 프로세스를 시작합니다. join() 메서드는 프로세스가 종료될 때까지 대기합니다.

 

 

Queue 클래스

Queue 클래스는 프로세스 간에 데이터를 안전하게 교환할 수 있는 방법을 제공합니다. 큐는 FIFO(First In, First Out) 방식으로 데이터를 저장하고 전달하며, multiprocessing.Queue를 사용하여 프로세스 간 데이터를 쉽게 공유할 수 있습니다.

from multiprocessing import Process, Queue

def worker(q):
    q.put("큐에 데이터 추가")

if __name__ == "__main__":
    q = Queue()
    p = Process(target=worker, args=(q,))
    p.start()
    print(q.get())  # 큐에서 데이터 가져오기
    p.join()

위 코드에서 Queue 객체를 생성하고, 이를 통해 프로세스 간에 데이터를 주고받을 수 있습니다. put() 메서드는 데이터를 큐에 추가하고, get() 메서드는 큐에서 데이터를 가져옵니다.

 

 

Pool 클래스

Pool 클래스는 여러 작업을 병렬로 처리하기 위해 고정된 수의 프로세스를 생성하고 관리합니다. Pool을 사용하면 간단한 코드로 병렬 처리를 수행할 수 있습니다. 특히 반복 작업이나 대규모 데이터 처리에 적합합니다.

from multiprocessing import Pool

def worker(x):
    return x * x

if __name__ == "__main__":
    with Pool(4) as p:
        results = p.map(worker, [1, 2, 3, 4])
    print(results)  # [1, 4, 9, 16]

위 코드에서 Pool 객체를 생성하고, map() 메서드를 사용해 여러 입력 값에 대해 병렬로 작업을 수행합니다. 이 방식은 입력 데이터가 많은 경우 특히 유용합니다.

 

 

 

 

멀티프로세싱 활용 시 주의사항

멀티프로세싱을 사용할 때는 다음과 같은 주의사항이 필요합니다:

  • 프로세스 간에 메모리를 공유하지 않으므로, 데이터를 공유할 때는 QueuePipe 같은 IPC(Inter-Process Communication) 기법을 사용해야 합니다.
  • Windows 환경에서는 if __name__ == "__main__" 블록 내에서 프로세스를 생성해야 합니다. 그렇지 않으면 프로세스가 무한히 생성되는 문제가 발생할 수 있습니다.
  • 멀티프로세싱은 멀티스레딩에 비해 프로세스 생성 비용이 크므로, 프로세스 간 통신 오버헤드를 고려해야 합니다.

 

 

실전 예제: 멀티프로세싱을 활용한 데이터 처리

이제 멀티프로세싱을 사용해 실제로 데이터 처리를 병렬로 수행하는 예제를 살펴보겠습니다. 이 예제에서는 여러 숫자의 리스트를 입력 받아 제곱을 계산하고, 결과를 반환합니다.

from multiprocessing import Pool

def square_number(n):
    return n * n

if __name__ == "__main__":
    numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    with Pool(processes=4) as pool:
        results = pool.map(square_number, numbers)
    print("결과:", results)

이 코드에서는 Pool을 사용해 숫자의 제곱을 계산하는 작업을 병렬로 처리했습니다. Pool 객체의 map 메서드는 입력 데이터를 자동으로 분할하여 병렬 처리를 수행합니다.

이제 파이썬에서 멀티프로세싱을 활용하여 어떻게 병렬 처리를 효율적으로 구현할 수 있는지 이해하게 되었습니다. 멀티프로세싱은 CPU 코어를 최대한 활용할 수 있는 강력한 도구이며, 적절한 상황에서 사용하면 성능을 크게 향상시킬 수 있습니다.