Python/Python

[Python] Concurrency 어떤 경우에 어떤 것을 사용하는게 좋을까 - 1

상쾌한기분 2022. 8. 12. 14:12
728x90
반응형

어느 상황에 어떤 Concurrency API를 사용하는게 좋을까

우리는 평소 개발 업무를 하면서 최대한 Response latency, Memory Usage 등을 줄이기 위해 노력을 한다.
예를 들어, ORM을 사용하는 경우 N+1 이나 1+N+aQuery Fetch를 줄이거나
또는, Algorithm을 이용해 시간복잡도를 최대한 적게 할려고 하는 등 말이다.

그럼 Python에서 비동기 소스를 개발할 때는 어떠한 경우에 어떻게 해야 좋은지 알아보자.

우선 Python이 제공하는 concurrency API는 다음과 같다.

  • Coroutine: asyncio module
  • Thread: threading module
  • Process: multiprocessing module

이 3가지의 module 중에 선택을 하게 될텐데 또 여기서 추가로 고려해야 하는 사항이 생긴다.
예를 들어,

  • threading을 사용하면, thread pool을 사용할지? Thread Class를 사용할지.
  • multiprocessing을 사용하면, process pool을 사용할지? Process Class를 사용할지.
  • thread pool을 사용하면, ThreadPool Class를 사용할지? ThreadPoolExecutor Class를 사용할지?
  • process pool을 사용하면, Pool Class를 사용할지? ProcessPoolExecutor Class를 사용할지?

적절한 API 선택 방법

  1. 주어진 상황이 CPU-Bound이냐? IO-Bound이냐?
    • 만약 IO-Bound라면, Corutine? Thread?
  2. 많은 임시 작업이 있냐? 한개의 복잡한 작업이냐?
  3. Pool? Executor?

1. 주어진 상황이 CPU-Bound이냐? IO-Bound이냐?

CPU Bound 작업 인가?

CPU-Bound 작업은 계산이 수행 되는가 여부이다. I/O 작업이 아니라.

  • 좌표, PI 등의 계산 작업
  • HTML, JSON, XML 등의 Parsing 작업
  • Text Processing
  • Simulation

I/O Bound 작업 인가?

I/O-Bound 작업은 읽거나 쓰는 작업이 수행 되는가 여부이다. (from or to device, socket, file 등)
I/O 작업은 Drive의 읽기/쓰기 속도, Network Connection Speed 등 환경에 영향을 받는다.

  • Drive로부터 파일 읽기/쓰기 작업
  • Standard Input, Output 작업(stdin, stdout, stderr)
  • Document Print
  • Download or Upload file
  • Query fetch
  • Network Request

추가로 고려할 점

multiprocessing은 계산에 중점을 둔 작업의 경우 적합하다.
하지만 Process간 많은 데이터를 통신을 해야 한다면 비적합하다.
왜냐하면 모든 공유되는 데이터들은 Serialize 되어야 하고 이는 추가적인 비용이 발생하기 떄문.

1.1 만약 IO-Bound라면, Corutine? Thread?

일반적으로 네트워크 통신 같은 경우에는 Coroutine으로 작성하는게 좋고
그 외의 경우는 Thread를 사용하는게 좋다.

이유는 Coroutine경량 Thread이기 떄문이다.

  • Single Request Thread가 관리 가능한 Thread의 수를 초과할 수 있다.
  • Thread의 수는 제어가 가능하다.

2. 많은 임시 작업이 있냐? 한개의 복잡한 작업이냐?

  • 짧은 생명 주기 or/and 많은 임시 작업 이라면, thread or Process pool
  • 긴 생명 주기 or/and 복잡한 작업 이라면, Thread Class or Process Class

추가로 고려할 점

  • 재사용? 단일 사용?
    • pool은 재사용에 적절하다. Process/Thread Class는 단일 사용에 긴 생명주기에 적적하다.
  • Multiple? Single?
    • pool은 많은 작업을 지원한다. Process/Thread Class는 단일 작업을 지원한다.

예시

  • 반복문으로 다른 Arguments로 함수를 호출한다고 하면 pool이 재사용에 적절하다.
  • 많은 파일을 다운로드 한다면 pool이 적절하다
  • 서버에서 리소스를 모니터링한다고 하면 Process/Thread Class가 한개의 역할과 긴 생명주기를 가져 적절하다.

Pool? Executor?

  • Executor는 취소 기능이 있다.
  • Executorcollections를 사용할 수 있다.
  • Pool은 모든 Task를 강제로 종료할 수 있다.
  • Pool은 map() 함수의 multiple parallel을 지원한다.
  • Pool은 작업의 excetion에 접근할 수 있다.

Ref

728x90
반응형