[파이썬] multiprocessing의 Pool 클래스

Posted by Euisuk's Dev Log on February 19, 2024

multiprocessing.Pool은 Python의 멀티프로세싱 모듈에서 제공하는 매우 유용한 클래스로, 병렬 처리를 위한 프로세스 풀을 관리합니다. 이 클래스를 사용하면 여러 프로세스에서 동시에 작업을 실행하는 복잡한 로직을 간단하게 처리할 수 있습니다.

본 블로그 포스트에서는 Pool의 주요 기능과 특징에 대해 자세히 설명하겠습니다.

Pool 클래스의 기능

  • 자동 프로세스 관리: Pool은 지정된 수의 프로세스를 자동으로 생성하고 관리합니다. 프로세스 풀에 작업을 할당하면, Pool은 이를 자동으로 프로세스에 분배하여 실행합니다.
  • 작업 분배: Pool의 map 메서드는 내장 함수 map()과 유사하게 작동하며, 여러 데이터 항목에 걸쳐 함수를 병렬로 적용합니다. 각 프로세스는 할당된 데이터 항목에 대해 지정된 함수를 실행하고, 결과를 수집합니다.
  • 결과 수집: 병렬 처리된 작업의 결과는 자동으로 수집되며, 작업이 완료되면 결과를 리스트로 반환합니다. 이는 병렬 처리 로직을 간결하게 유지하면서도 결과를 쉽게 처리할 수 있도록 해줍니다.

예시 코드 설명

1
2
with Pool(processes=3) as pool:
    results = pool.map(process_file, files)
  • Pool(processes=3): 프로세스 풀을 생성하고, 풀에는 3개의 프로세스가 포함됩니다. 시스템에 따라 프로세스 수를 조절하여 최적의 성능을 달성할 수 있습니다.
  • pool.map(process_file, files): process_file 함수를 files 리스트의 각 항목에 병렬로 적용합니다. process_file 함수는 각 파일을 처리하고, 처리된 데이터를 반환합니다. map 메서드는 모든 작업이 완료되기를 기다린 후, 각 작업의 반환값을 순서대로 담은 리스트를 results에 할당합니다.

Pool 사용의 이점

  • 코드의 간결성: Pool을 사용하면, 병렬 처리를 위한 복잡한 프로세스 생성, 시작, 종료 로직을 직접 관리할 필요가 없습니다. Pool이 이 모든 과정을 자동으로 처리합니다.
  • 유연한 작업 분배: map 외에도 apply, apply_async, imap 등 여러 메서드를 제공하여 다양한 방식으로 작업을 분배하고 결과를 수집할 수 있습니다.
  • 자원 활용 최적화: 시스템의 CPU 코어를 효율적으로 활용하여 병렬 처리 성능을 최적화할 수 있습니다. 프로세스 수를 조정하여 시스템 자원과 작업의 요구 사항에 맞게 최적화할 수 있습니다.

start(), join()과의 차이점

multiprocessing.Pool과 직접 Process 객체를 사용하여 .start()와 .join()을 호출하는 방식은 모두 Python에서 멀티프로세싱을 구현하는 데 사용되지만, 각각의 사용법과 적용 시나리오에서 차이가 있습니다. 아래에서는 이 두 방법의 주요 차이점을 비교하겠습니다.

multiprocessing.Pool

  • 자동화된 프로세스 관리: Pool 클래스는 프로세스 풀을 자동으로 관리합니다. 프로세스의 생성, 실행, 종료 등을 사용자가 직접 제어할 필요 없이 Pool이 처리합니다.
  • 간편한 작업 분배: map, apply, imap, starmap 등의 메서드를 통해 여러 작업을 프로세스 풀에 쉽게 분배할 수 있습니다. 이는 대량의 데이터를 병렬 처리할 때 특히 유용합니다.
  • 결과 수집의 용이성: Pool을 사용하면 작업의 결과를 자동으로 수집하고 정렬할 수 있습니다. 이는 작업 관리와 결과 처리를 간소화합니다.
  • 적용 시나리오: 대규모 데이터 처리, CPU 집약적 연산, 데이터 병렬 처리 등 다수의 독립적인 작업을 병렬로 수행해야 할 경우 적합합니다.

Process.start()와 Process.join()

  • 세밀한 프로세스 제어: Process 객체의 .start()와 .join()을 사용하면 각 프로세스의 시작과 종료를 더 세밀하게 제어할 수 있습니다. 각 프로세스의 생성부터 종료까지 모든 단계를 직접 관리합니다.
  • 유연한 프로세스 관리: 특정 프로세스에 대한 상세한 제어가 필요한 경우, 예를 들어 특정 프로세스의 우선순위를 설정하거나, 특정 조건에서만 프로세스를 시작하고자 할 때 유용합니다.
  • 수동 결과 수집: 각 프로세스의 결과를 수집하는 로직을 사용자가 직접 구현해야 합니다. 이는 Queue, Pipe, 공유 메모리 등의 방법을 사용하여 프로세스 간 통신을 설정해야 함을 의미합니다.
  • 적용 시나리오: 개별 프로세스에 대한 높은 수준의 제어가 필요하거나, 프로세스 간 복잡한 통신이 요구되는 경우 적합합니다.

정리

  • 자동화와 제어: Pool은 프로세스 관리를 자동화하고 작업 분배와 결과 수집을 간소화하는 반면, Process.start()와 .join()은 개별 프로세스에 대한 더 높은 수준의 제어를 제공합니다.
  • 작업 분배: Pool은 다수의 작업을 쉽게 분배하고 자동으로 결과를 수집할 수 있는 반면, Process를 사용하는 방식은 각 작업의 실행과 결과 수집을 수동으로 관리해야 합니다.
  • 적용 시나리오: 복잡도가 낮고 대규모 데이터를 독립적으로 처리해야 하는 경우 Pool이 더 적합할 수 있으며, 프로세스 간 복잡한 상호작용이 필요하거나 높은 수준의 제어가 요구되는 경우 Process를 직접 사용하는 것이 더 적합할 수 있습니다.

각 방법의 선택은 구현해야 하는 작업의 복잡성, 필요한 제어 수준, 그리고 결과 데이터를 어떻게 수집하고 처리할지에 따라 달라질 수 있습니다.