바운드
- Bound의 뜻: 경계, 한계
- 프로세스 진행이 제한되는 것을 의미한다. 원인에 따라 분류해보면 다음과 같다.
CPU 바운드
- 프로세스 진행 속도가 CPU 속도에 의해 제한됨을 의미한다.(CPU Burst가 큰 프로세스)
- 복잡한 수학 수식을 계산하는 경우 프로그램의 실행속도가 느려진다.
- 동영상 편집, 머신러닝 등
버스트(Burst)란
- 어떤 현상이 짧은 시간 안에 집중적으로 일어나는 일
I/O 바운드
-
프로그램이 실행될 때 실행 속도가 I/O에 의해 제한됨을 의미한다.(I/O Burst가 큰 프로세스)
-
사용자가 입력을 하고 해당하는 입력에 대해 더하기 100을 한 결과값을 출력해주는 프로그램이 있다면 사용자가 입력을 하는 데 걸리는 시간에 따라서 프로그램의 실행 속도가 결정된다.
-
인터넷에서 사진을 수집해서 저장하는 프로그램은 인터넷 속도가 전체 프로그램의 성능을 결정한다.
-
컴퓨터끼리 통신을 할 때에도 I/O바운드가 발생한다.
-
예시: 일반적인 백엔드 API, 파일을 읽거나 쓰는 작업 등
메모리 바운드
캐시 바운드
- 프로세스 진행률이 사용 가능한 캐시의 양과 속도에 의해 제한되는 비율을 의미한다.
- 캐시에 맞는 것보다 더 많은 데이터를 단순히 처리하는 작업은 캐시에 바인딩된다.
I/O 바운드는 메모리 바운드보다 느리고 캐시 바운드는 CPU 바운드보다 느리다.
I/O 바인딩 솔루션은 반드시 더 많은 메모리를 확보 할 필요는 없다.
경우에 따라 액세스 알고리즘은 I/O, 메모리 또는 캐시 제한을 중심으로 설계 될 수 있다.
블로킹 vs 논 블로킹
- 블로킹: 어떤 작업을 하는 동안 다른 작업을 못하게 막는 것을 의미한다. 따라서 블로킹은 직렬로 실행될 수 밖에 없다.
- 논 블로킹: 다른 작업에 상관없이 작업이 실행되는 것이다.
동기 vs 비동기
동기
- 코드가 동기적으로 동작한다. -> 코드가 반드시 작성된 순서 그대로 실행된다.
- 세 군데에 짜장면 배달을 갔는데 간 곳마다 손님이 짜장면을 다 먹을 때 까지 기다렸다가 그릇을 수거하고 다음 목적지로 배달하러 간다면 이는 동기적으로 일을 처리한 것이다.
- 중간에 모여서 정보를 교환하고 일관성을 유지하는 작업을 한다. 따라서 일을 빨리 끝낸 쓰레드나 프로세스가 대기해야 하므로 시간 낭비가 발생할 수 있다.
비동기
- 코드가 비동기적으로 동작한다. -> 코드가 반드시 작성된 순서 그대로 실행되는 것이 아니다.
- 세 군데에 짜장면 배달을 갔는데 일단 배달부터 먼저 하고 손님이 다 먹은 후 그릇을 수거한다면 이는 비동기적으로 일을 처리 한 것이다.
- 각 작업을 완전히 독립적으로 진행하므로 대기할 필요가 없다.
- 동시성이나 병렬성 구현 시 일반적으로 비동기식이 효율이 좋지만 알고리즘에 따라서 동기식이 나을 수도 있다.
루틴
- 일련의 명령, 코드의 흐름을 의미한다(프로그램의 순서).
메인 루틴
서브루틴
- 메인 루틴에 종속된 루틴.
- 우리가 알고 있는 일반적인 함수나 메서드(메인 루틴을 보조하는 역할).
- 하나의 진입점과 하나의 탈출점이 있는 루틴이다.
- 프로그램이 실행되면 서브 루틴은 별동의 공간(스코프)에 해당 로직들을 모아 놓고 있다.
- 서브 루틴이 호출될 때, 해당하는 로직들의 공간으로 이동했다가 return을 통해 원래 호출시점(메인 루틴)으로 돌아오게 된다.
def subroutine():
print("ABC")
def main():
print("123")
subroutine()
print("456")
subroutine()
print("789")
코루틴
- 다양한 진입점과 다양한 탈출점이 있는 루틴.
- 코루틴은 서브 루틴과는 달리 해당 로직들이 진행되는 중간에 멈추어서 특정 위치로 돌아 갔다가 다시 코루틴에서 진행되었던 위치로 돌아와 나머지 로직을 수행할 수 있다.
- 파이썬 비동기 함수는 코루틴 함수로 만들 수 있다.
def coroutine():
print("ABC")
yield
print("DEF")
yield
print("GHI")
yield
def main():
coro = coroutine()
print("123")
next(coro)
print("456")
next(coro)
print("789")
next(coro)
프로세스와 스레드
프로세스
- 프로그램: 어떤 문제를 해결하기 위해 컴퓨터에게 주어지는 처리 방법과 순서를 기술한 일련의 명령문(코드)의 집합체
- 프로그램 실행 -> 해당 프로그램의 작성된 코드들이 주 메모리로 올라와서 작업이 진행된다.
- 프로그램은 저장장치에 저장된 정적인 상태이다.
- 프로세스란 실행을 위해 프로그램이 주 메모리에 올라온 동적인 상태를 말한다.
- 프로세스가 생성되면 CPU는 프로세스가 해야할 작업을 수행한다.
스레드
- 프로세스가 생성되면 CPU는 프로세스가 해야할 작업을 수행한다. 이 때 CPU가 처리하는 작업의 단위가 바로 스레드 이다.
- 즉 스레드란 프로세스 내에서 실행되는 여러 작업의 단위이다.
- 스레드는 사용자 수준 스레드와 커널 수준 스레드로 나뉜다.
- 스레드가 한 개로 동작하면 싱글 스레드, 여러 개로 동작하면 멀티 스레딩이라 한다.
- 멀티 스레딩에서 스레드는 다수의 스레드들 간 메모리 공유와 통신이 가능하다.
- 멀티 스레딩은 자원의 낭비를 막고 효율성을 향상시키지만 한 스레드에 문제가 생기면 전체 프로세스에 영향을 미친다는 단점도 있다.
- 파이썬의
asyncio
는 싱글 스레드로 동작한다.
동시성(병행성) vs 병렬성
동시성(Concurrency)
-
동시성이란 한 번에 여러 작업을 동시에 다루는 것을 의미한다.
-
여러 개의 일들이 동시에 진행되는 것 처럼 처리하는 것을 말한다.
-
동시성은 논리적 개념으로 멀티 스레딩에서 사용되기도 하고 싱글 스레드에서 사용되기도 한다. 또한 싱글 코어 뿐만 아니라 멀티 코어에서도 각각의 코어가 동시성을 사용할 수 있다.
-
동시에 작동하는 것 처럼 빠르게 여러 프로그램을 돌아가면서 작업을 처리하는 것이지 실제로 모든 작업이 동시에 실행되고 있는 것은 아니다.
-
예를 들어 라면, 케이크, 파스타 주문이 한꺼번에 들어온 상황에서 라면 물을 끓이는 동안 케이크 반죽을 만들고 파스타 재료를 손질하고 다시 라면을 요리하는 방식이다.
-
이렇게 여러 작업을 번갈아서 하기 때문에 컨텍스트 스위칭이 필요하다.
-
주로 I/O 바운드에 사용된다.
병렬성(Parallelism)
-
병렬성은 한 번에 여러 작업을 병렬적으로 처리하는 것을 의미한다. 동시에 여러 태스크를 처리하는 것이다.
-
병렬성은 물리적 개념으로 멀티코어에서 여러 작업을 병렬적으로 수행한다.
-
라면, 케이크, 파스타 주문이 한꺼번에 들어온 상황에서 세 명의 각기 다른 요리사가 요리를 시작하는 방식
-
멀티 코어 단위에서 동작할 수 있지만 스레드 단위에서도 동작할 수 있다.
-
병렬성과 동시성은 공존할 수 있다.
-
파이썬에선 GIL(Global Interpreter Lock)으로 인해 멀티 스레딩으로 병렬성 작업을 수행할 수 없다.
-
주로 CPU 바운드에 사용된다.
파이썬 멀티 스레딩 & 멀티 프로세싱
멀티 스레딩의 단점
- 멀티 스레딩은 스레드끼리 자원을 공유한다. 그런데 하나의 자원을 동시에 여러 스레드가 가져가려는 상황에선 충돌이 발생할 수 있다. 이 경우 하나의 스레드가 다른 스레드에 의해 차단될 수 있다.
- 파이썬 GIL은 이러한 문제점을 막는다.
전역 인터프리터 잠금(GIL, Global Interpreter Lock)
- GIL이란 CPython에서 한 번(한 순간)에 한 개의 스레드만 유지하는 잠금장치이다.
- GIL은 기본적으로 한 스레드가 다른 스레드를 차단하여 제어를 얻지 못하도록 한다.
- GIL에 의해서 파이썬으로는 스레드가 병렬적인 연산을 수행하기 어렵다.
- 다른 언어에서는 멀티스레딩을 동시성과 병렬성에 모두 활용할 수 있지만 파이썬은 현실적으로 동시성에만 활용 가능하다.
- 파이썬 멀티스레딩은 동시성을 이용하여 IO 바운드 코드에서 유용하게 사용할 수 있지만 CPU 바운드 코드에 대해서는 GIL에 의해 원하는 결과를 얻기 어렵다.
- 따라서 파이썬으로 병렬성 연산을 수행하는 방법으로는 코루틴이 추천된다.
- C++ 등 적합한 언어로 만든 모듈을 파이썬에서 활용하면 멀티스레딩을 자유롭게 사용 할 수 있다.
- GIL은 GPU 멀티스레딩에는 영향을 주지 않는다.
- 파이썬 3.13 부터는 GIL을 해제할 수 있다.
멀티 프로세싱의 장점
- 멀티 프로세싱으로 이러한 멀티 스레딩을 단점을 보완할 수 있다.
멀티 프로세싱의 단점
- 프로세스 간 메모리를 공유하지 않기 때문에 서로 통신을 해야 하며, 그에 대한 비용이 있다.
문제 | 예시 | 전략 | 멀티스레딩 | 멀티프로세싱 | Asyncio |
---|
I/O 바운드 | 웹 스크래핑 | 동시성 | O | △ | O |
CPU 바운드 | 수학 계산 | 병렬성 | X (GIL) | O | X |
- 이 중 두 가지 혹은 세 가지를 함께 사용할 수도 있다.
참고자료