본문 바로가기
코딩취미/Python

Python multiprocessing 모듈: 특징, 장점, 및 사용 방법 정리

by 브링블링 2024. 12. 10.
반응형

Python multiprocessing 모듈: 특징, 장점, 및 사용 방법 정리

Python의 multiprocessing 모듈은 다중 프로세스를 활용하여 CPU 성능을 극대화하고, 병렬 처리를 통해 작업 속도를 높이는 데 사용됩니다. 특히, Python의 GIL(Global Interpreter Lock) 제한을 우회하여 멀티코어 CPU에서 효율적인 병렬 처리를 가능하게 합니다.


특징

  1. 병렬 처리 지원:
    • 여러 프로세스를 생성하여 작업을 병렬로 실행할 수 있습니다.
    • GIL의 영향을 받지 않으므로 CPU 바운드 작업에 적합합니다.
  2. 독립적인 프로세스 메모리:
    • 각 프로세스는 독립적인 메모리 공간을 가지므로, 메모리 충돌이나 동기화 문제를 최소화합니다.
  3. 다양한 통신 메커니즘:
    • 프로세스 간 데이터를 교환하기 위한 Queue, Pipe, Value, Array 등의 통신 도구를 제공합니다.
  4. 유연한 프로세스 생성 방식:
    • spawn, fork, **forkserver**와 같은 다양한 프로세스 시작 방식을 지원합니다.
  5. Pool 지원:
    • 프로세스 풀을 생성하여 작업을 쉽게 분배하고 관리할 수 있습니다.

장점

  1. GIL 우회:
    • Python의 GIL 제약 없이 멀티코어 CPU를 활용하여 높은 성능을 제공합니다.
  2. 안정성:
    • 각 프로세스가 독립적인 메모리 공간을 가지므로, 메모리 접근 충돌이 발생하지 않습니다.
  3. 병렬 성능 향상:
    • 대규모 데이터 처리, 이미지 처리, 머신러닝, 비디오 렌더링 등 CPU 바운드 작업에서 성능을 극대화할 수 있습니다.
  4. 높은 유연성:
    • 프로세스 기반이므로, 병렬 처리뿐만 아니라 멀티태스킹 애플리케이션에도 적합합니다.
  5. 표준 라이브러리 제공:
    • 외부 라이브러리를 설치할 필요 없이 Python의 내장 모듈로 제공됩니다.

반응형

사용 방법

1. 기본적인 프로세스 생성

multiprocessing.Process를 사용하여 프로세스를 생성하고 실행합니다.

import multiprocessing
import os

def worker_function(name):
    print(f"Worker {name} is running in process {os.getpid()}")

if __name__ == "__main__":
    # 프로세스 생성
    process1 = multiprocessing.Process(target=worker_function, args=("A",))
    process2 = multiprocessing.Process(target=worker_function, args=("B",))

    # 프로세스 시작
    process1.start()
    process2.start()

    # 프로세스 완료 대기
    process1.join()
    process2.join()

    print("Main process finished")

 

2. 프로세스 간 통신

Queue를 사용하여 프로세스 간 데이터를 교환합니다.

import multiprocessing

def worker(queue):
    queue.put("Data from worker")

if __name__ == "__main__":
    queue = multiprocessing.Queue()

    # 프로세스 생성 및 실행
    process = multiprocessing.Process(target=worker, args=(queue,))
    process.start()
    process.join()

    # Queue에서 데이터 읽기
    print(f"Received from worker: {queue.get()}")

 

3. 프로세스 풀 사용

Pool을 사용하여 작업을 병렬로 처리합니다.

from multiprocessing import Pool

def square(x):
    return x * x

if __name__ == "__main__":
    data = [1, 2, 3, 4, 5]

    # 프로세스 풀 생성
    with Pool(4) as pool:
        results = pool.map(square, data)

    print(f"Squared results: {results}")

 

4. CPU 코어 활용

multiprocessing.cpu_count()를 사용하여 시스템의 CPU 코어 개수를 확인하고, 병렬 작업에 활용할 수 있습니다.

import multiprocessing

def worker_task(task_id):
    print(f"Task {task_id} is running")

if __name__ == "__main__":
    num_cores = multiprocessing.cpu_count()
    print(f"Number of CPU cores: {num_cores}")

    with multiprocessing.Pool(num_cores) as pool:
        pool.map(worker_task, range(10))

주의사항

  1. if __name__ == "__main__": 블록 필수:
    • Windows 및 macOS에서는 프로세스 생성 시 메인 스크립트를 다시 실행하므로, 코드가 무한 재귀 실행되지 않도록 반드시 if __name__ == "__main__": 블록을 사용해야 합니다.
  2. freeze_support() 필요:
    • PyInstaller로 패키징 시, multiprocessing.freeze_support()를 추가하여 멀티프로세싱이 정상 동작하도록 설정합니다.
  3. 데이터 직렬화:
    • 프로세스 간 데이터를 전달할 때, 직렬화 가능한 객체만 사용할 수 있습니다. (예: 기본 데이터 타입, 리스트, 딕셔너리 등)
반응형