[개발 정리]

병행 및 병렬 프로그래밍 야매 정리 (1)

hskimim 2024. 7. 23. 02:17

참조

- chatgpt

- https://gmlwjd9405.github.io/2018/09/14/process-vs-thread.html

- https://ivdevlog.tistory.com/3

- https://hhj6212.github.io/programming/python/2021/04/18/python-multi.html

- https://velog.io/@wonhee010/%EB%8F%99%EA%B8%B0vs%EB%B9%84%EB%8F%99%EA%B8%B0-feat.-blocking-vs-non-blocking


배우는 중이라 틀린 정보가 있을 수 있는데, 업데이트되는 공부 내용이 있으면 계속 고치겠습니다. 교정해주시면 감사하겠습니다..! (_ _)

 

목록

1. CPU

2. Core

3. Process

4. Thread

5. multi-core vs multi-processing

6. multi-processing vs multi-threading


 

CPU

- 전체 시스템의 중앙 처리 장치 (hardware)

 

Core

- CPU 내부에 있는 처리 장치 (hardware)

- 각 Core는 독립적으로 작업을 수행, 개별 연산 장치

 

Process

- 프로그램의 인스턴스

- OS로부터 자원을 할당받는 작업의 단위, 할당된 자원을 소유

- code, data, stack, heap 으로 되어 있는 독립된 메모리 영역

- 하나의 process는 최소 하나의 thread(main thread + alpha) 를 갖고 있다

- process 간 통신은 IPC 사용

 

Thread

- process가 할당받은 자원을 이용하는 작업의 단위, 할당받은 자원을 사용

- process 안에 있는 thread들은 code, data, heap 을 서로 공유하고, stack만 따로 할당

- 데이터 공유와 통신이 용이, but 동기화 기법 필요

 

multi-core vs multi-processing

- multi-core에서만 multi-processing 을 할 수 있는건 아니고, single core에서도 할 수 있음.

- 시간 분할 방식(time slicing)을 사용해서 CPU 시간을 여러 프로세스에 나눠줌. 

- 프로세스 간에 context switching 을 하여, 여러 프로세스가 동시에 실행되는 것처럼 보이게 함

    - asynchronous 와의 관계?

    - process 간 잦은 context switching 은 overhead 를 발생시킴

        - context switching : CPU가 한 process (or thread)의 상태를 저장하고 다른 process(or thread)의 상태를 load 하는 과정을 의미

        - overhead :

            - 상태 저장 및 복원하는 과정이 오래 걸림

            - cache miss (이거 뭔지 모르겟음)

            - pipeline flush : CPU가 명령어 pipeline 을 사용해서 명령어를 효율적으로 처리하는데, switching 하게 되면 pipeline flush가 발생, 다시 채워줘야 해서, cpu 명령어 처리 효율이 떨어짐

            - 등등...

        - overhead 안좋은 이유: 수행 시간 느려지고, CPU 의 비효율적 사용 증가 (발열, 전력 소모 등)

 

- thread 간 context switching : 이 경우에도 overhead 가 발생할 수 있지만, 동일한 프로세스 내의 모든 스레드는 동일한 메모리 공간을 공유하기에, 오버헤드가 상대적으로 적음. 레지스터 상태만을 저장하고 복원하면 된다고 함. 레지스터 안에는 작업에 필요한 데이터와 명령어 위치가 저장되고 있음. process 간 스위칭에서는 이것보다는 훨씬 더 많은 것들을 저장 및 복원해야 함. (너무 많아서 생략)

 

(복붙)

  • 스레드 간 컨텍스트 스위칭: 레지스터 상태, 프로그램 카운터, 스택 포인터 등의 상태 저장 및 복원만 필요합니다. 스레드는 동일한 주소 공간을 공유하므로 주소 공간 전환이 필요하지 않습니다.
  • 프로세스 간 컨텍스트 스위칭: 레지스터 상태, 프로그램 카운터, 스택 포인터 저장 및 복원 외에도 주소 공간 전환, 페이지 테이블 전환, 캐시 미스, 커널 데이터 구조 전환, 파일 및 I/O 상태 관리 등의 추가 작업이 필요합니다.

multi-processing vs multi-threading

위에서 많이 말해서 적절한 사용 경우만 이야기한다.

 

multi-threading : I/O bound 작업에 적합

- process가 긴 시간의 I/O 를 만나면 cpu가 idle 상태가 된다. 이걸 그대로 두지 않고 다른 일을 하게 하는 것

 

multi-processing : CPU bound 작업에 적합

 

 

blocking vs non-blocking <-> synchronous vs asynchronous

아는 선배가 이 포인트를 잡고 가면 좋다고 해서, 검색해서 정리해본다. 일단 blocking 이라는 용어가 가장 빈번하게 사용되는 맥락은 I/O 이다. 그래서 blocking I/O 라는 표현이 더욱 적합하다는데, 일단 쓰는건 blocking vs non-blocking 이라고 하겠다. (blocking 은 스레드 동기화, 자원 획득 등 다양한 분야에서 쓰인다고 한다)

 

blocking vs non-blocking

- 함수가 바로 return 하냐 마냐

    - 호출된 함수가 바로 return 하면 non-blocking

    - 호출된 함수가 자신의 작업을 끝날 때까지 기다리면 blocking

 

synchronous vs asynchronous

-> 함수의 작업 완료 여부를 누가 신경쓰냐

    - 호출하는 함수(A)가 호출되는 함수(B)에게 callback 을 전달, 함수가 끝나면 B가 A에게 받은 callback 실행, A는 callback 전달하면 함수에는 신경 안쓰면 asynchronous

    - 호출하는 함수(A)가 호출하고 return 을 바로 받든 (non-blocking), 완료되고 받는(blocking) 자기가 return 값을 신경쓰면 synchronous

 

기가 막힌 사진을 다른 블로그에서 봐서 첨부한다. 더 자세한 설명은 아래 이미지의 첨부를 따라가면 있다.

https://velog.io/@wonhee010/%EB%8F%99%EA%B8%B0vs%EB%B9%84%EB%8F%99%EA%B8%B0-feat.-blocking-vs-non-blocking

 

synchronous + blocking (read/write) : 함수를 호출하고 return 이 완료될 때까지 기다렸다가 완료되면 다른 일을 함

synchronous + non-blocking (read/write with polling) : 결과가 없으면 바로 return, 하지만 결과를 직접 호출자가 받아야 하니, 주기 적으로 확인을 함. 일종의 폴링

asynchronous + blocking : 호출자(A)가 callback 넘겨주고, return이 올 때까지 딴 일은 못하고 기다림. 굳이 이점이 없다고 함

asynchronous + non-blocking : callback 과 함께 호출 + 바로 return, 다른 일하고 있으면 호출되었던 함수가 끝나면 callback 을 넘겨받으면 그때 봐주면 됨.

 

(복붙)

 

  • Blocking and Synchronous:
    • 작업이 순차적으로 이루어지며, 하나의 작업이 완료될 때까지 다른 작업을 수행하지 않습니다.
    • 예: 전통적인 함수 호출 방식, I/O 작업이 완료될 때까지 기다림.
  • Blocking and Asynchronous:
    • 비동기적으로 작업을 요청하더라도 결과를 기다리는 동안 블로킹 상태가 됩니다.
    • 예: 비동기 호출 후 결과를 기다리며 다른 작업을 수행하지 않는 방식.
  • Non-blocking and Synchronous:
    • 덜 일반적이며, 일반적으로 Non-blocking 작업은 비동기적일 때 유용합니다.
    • 예: 작업을 요청하고 바로 제어를 반환받지만, 이후 작업이 완료될 때까지 다른 작업을 수행하지 않는 방식.
  • Non-blocking and Asynchronous:
    • 작업을 비동기적으로 요청하고, 작업이 완료되면 콜백 함수나 다른 메커니즘을 통해 결과를 처리합니다.
    • 예: 이벤트 루프를 사용하는 Node.js, 비동기 I/O 작업.

 

concurrency vs parallelism vs asyncio

 

- asyncio

    - non-blocking + asynchronous 

 

concurrency vs parallelism 이 비교대상에 오를 레벨인거 같다. (asyncio 보다 상위 개념인 것 같음)

Concurrency is about dealing with lots of things at once. Parallelism is about doing lots of things at once.

A system is said to be concurrent if it can support two or more actions in progress at the same time. A system is said to be parallel if it can support two or more actions executing simultaneously

 

- concurrency

    - 위에서 다룬 blocking I/O 와 sync 들의 조합으로는 표현할 수 없는 상위 개념

        - 4가지 모두로 concurrency를 구현할 수 있다고 한다.

            - 예로 들어, multi-threading 을 사용하면 sync + blocking 인데 여러 스레드가 동시에 돌거나 context switching 을 하기에 시행 시간이 짧아진다.

    - 여러 작업을 동시에 처리하는 능력 의미, but 실제로 동시에 실행되는 것을 보장하지는 않음 (뭔 소리)

    - 그런 것처럼 보이도록 만드는 것이 목표

- parallelism

    - 여러 작업이 실제로 동시에 실행되는 것을 의미

 

multi-threading in Python

multi-threading 을 Python에서 사용하면 GIL때문에 concurrency가 실행됨

Concurrency with Multi-threading:

- Concurrency는 여러 스레드가 동일한 CPU 코어에서 번갈아 가며 실행되는 경우입니다. 이는 실제로 동시에 실행되지 않지만, 빠른 컨텍스트 전환을 통해 동시에 실행되는 것처럼 보이게 만듭니다.