병행 및 병렬 프로그래밍 야매 정리 (1)
참조
- 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
배우는 중이라 틀린 정보가 있을 수 있는데, 업데이트되는 공부 내용이 있으면 계속 고치겠습니다. 교정해주시면 감사하겠습니다..! (_ _)
목록
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
기가 막힌 사진을 다른 블로그에서 봐서 첨부한다. 더 자세한 설명은 아래 이미지의 첨부를 따라가면 있다.
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 코어에서 번갈아 가며 실행되는 경우입니다. 이는 실제로 동시에 실행되지 않지만, 빠른 컨텍스트 전환을 통해 동시에 실행되는 것처럼 보이게 만듭니다.