05_Concurrency and Parallelism

Copes·2021년 12월 21일

Python

목록 보기
5/7
post-thumbnail

Concurrency

  • 병행성(Concurrency)
    • 한 컴퓨터(CPU, 스레드)가 여러 일을 동시에 수행
    • 어디까지 작업을 수행했는지 알고 있어야 한다. 그런 개념으로 사용하는 것이 Closure와 같은 것들
  • 병렬성(Parallelism)
    • 여러 컴퓨터가 여러 일을 동시에 수행
    • 속도, 각자 맡은 일을 수행함으로써 전체적인 속도가 빨라진다.

Generator/Iterator

  • Generator(제너레이터) : Iterator를 리턴(생성)하는 함수, yield를 사용하며 메모리 적재 방식에서 Iterator와 차이가 있다

  • Iterator(이터레이터) : 반복 가능한 객체

    단순히 yield를 쓰냐 안쓰냐의 차이도 있지만.

    • 가장 큰 차이점은
      • Generator(제너레이터)는 각각의 yield에서 한번 실행 시킨 후 대기 상태에 들어가 결과를 반환, 이후 다음 코드를 진행하여 또 다시 yield를 만날 경우 대기 상태에 들어가 결과를 반환하는 방식
      • Iterator(이터레이터)는 모든 동작은 완료한 후 결과를 한번에 메모리 적재하는 방식
  • 파이썬 반복 가능한 타입(iterable)

    • collections, textfile, list, dict, set, tuple, unpacking, *args, iterable하게 구현된 클래스 등
  • Generator 패턴
    1. 지능형 리스트, 딕셔너리, 집합 -> 데이터 양 증가. 증가 후 메모리 사용량 증가 -> 제너레이터 사용 권장
    2. 단위 실행 가능한 코루틴(Coroutine) 구현과 연동
    3. 작은 메모리 조각 사용

Code 1
Code 2

Coroutine

  • Coroutine(코루틴)
    • 단일(싱글) 스레드.
    • 스택을 기반으로 동작하는 비동기 작업
  • Thread(스레드)
    • OS에서 관리, CPU core에서 실시간, 시분할 비동기 작업 -> 멀티 스레드
  • yield, send를 통해 메인 <-> 서브
    • 코루틴 제어, 상태, 양방향 전송
  • 서브 루틴 : 메인 루틴 호출 -> 서브 루틴에서 수행(흐름 제어)
  • 코루틴 : 루틴 실행 중 중지 -> 동시성 프로그래밍
    -> 스레드에 비해 overhead 감소(단일 스레드에서 진행하기 때문에 상태를 저장하는 등의 작업을 수행하는 overhead가 필요 없다.)
    • 멀티 스레드 : 복잡. 공유되는 자원때문에 교착 상태Context Switching 비용이 생기며, 자원 소비 가능성 증가.
  • Python 3.7이상에서는 def -> async, yield -> await로 사용할 수 있다.
  • 함수인지 코루틴인지 명확하지 않을 수 있기 때문에. 이렇게 명시적으로 작성할 수 있다.

Code 3

Futures, Parallelism

비동기 작업 수행

  • 지연 시간(Block) CPU 및 리소스 낭비 방지 -> (File)Network I/O 관련 작업 -> 동시성 활용 권장(제어권을 다른 데 넘겨서 다른 작업 수행하기 위해서.)

  • 비동기 작업에 적합한 프로그램일 경우 압도적으로 성능 향상

  • Futures

    • 비동기 실행을 위한 API를 고수준으로 작성 -> 사용하기 쉽도록 개선
    • 기존에 import threading, multiprocessing 둘 다 사용해야 했으나 편리하게 변경됨.
    1. 멀티스레딩/멀티프로세싱 API 통일 -> 매우 사용하기 쉬움
    2. 실행 중인 작업 취소, 완료 여부 체크, 타임 아웃 옵션, 콜백 추가, 동기화 코드 매우 쉽게 작성 -> Promise 개념(비동기 작업의 결과를 나타내는 객체)
  • GIL(Global Interpreter Lock)

    • 두 개 이상의 스레드가 동시에 실행될 때 하나의 자원을 액세스 하는 경우
      -> 문제가 일어나는 것을 방지하기 위해 GIL이 실행된다
    • GIL이 실행되면 -> 리소스 전체에 Lock이 걸린다.
      • Lock이 걸려 두 개 이상의 스레드가 동시에 접근이 불가하면서
      • Context Switching 비용도 발생하므로 멀티 스레드를 사용하는 것이 싱글 스레드를 사용하는 것보다 오히려 효율이 떨어지는 경우가 발생할 수 있다.

Code 4

2가지 패턴 실습

  • concurrent.futures map
  • concurrent.futures wait, as_completed
    -> convoy effectfail등을 세부적으로 관리할 수 있어야 한다.
    • wait : timeout을 줄 수 있다.
    • as_completed : 먼저 처리된 것을 바로 처리할 수 있다.
      -> 작업이 실행되고 바로 다른 작업을 수행하기 위해서 주로 사용.

Code 5

0개의 댓글