실무...하면 대표적인 키워드 병렬처리...
특히 빅데이터가 핫해진 이유로 꼽히는 하둡도, 분산 처리 플랫폼...
결국 핵심은
'백지장도 맞들면 낫다'이다.
한 사람이 1시간 걸리는 작업을
두 사람이 하면 30분만에 끝낼 수 있다는 것
즉, 소요 시간이 줄어든다는 것이다.
그럼 무조건 병렬처리하면 좋은거 아닌가?
이건 명백히 틀렸다.
본인은 학부생시절 CPU, RAM 빵빵한 노트북, 데스크탑에서 개발을 진행할 때는 별 생각 없이 병렬처리로 코드를 구현했다.
하지만 GCP, AWS와 같은 클라우드 서비스에서 1~2코어에 2기가 램을 가진 가상 머신에서 프로그램을 돌리면서
병렬 처리의 Trade-off를 뼈저리게 깨달았다.
본론으로 돌아와서, 앞에서 말했듯 병렬처리는 기본적으로 '일하는 사람을 늘려서 소요 시간을 줄인다'에 베이스를 둔다.
다시 말해, 컴퓨팅 자원(돈)을 주고, 빠른 처리 속도(시간)를 얻는 관계가 된다.
따라서, 처리 속도향상 (시간 단축)의 가치가 컴퓨팅 자원 추가에 필요한 금액보다 높다면 병렬처리를 도입하고,
아니라면 조금 느린 상태를 유지하되, 자본을 아끼는 선택이 올바르다고 볼 수 있다.
더 빠른 이해를 위해 본인의 예시를 들자면,
본인은 일전에 수행했던 프로젝트에서 대용량 텍스트파일을 처리하는 속도를 높이기 위해 하나의 텍스트 파일을 여러개의 청크로 나누어
멀티 프로세스로 병럴처리한 경험이 있다.
처리 성능은 다음과 같다.
멀티 프로세스 도입 전에는 812초가 소요되는 작업이 도입 후 36초로 단축되었다.
물론 그와는 반대로 CPU 사용률도 20% 정도에서 100%로 급상승했다.
(이때 처음으로 병렬처리의 맛을 보고 여기저기 죄다 병렬처리하고 다닌건 비밀)
그럼 멀티 프로세스와 멀티 스레드는 뭐가 다른가?
앞서 언급한 프로젝트를 수행할 당시에는 멀티 스레드는 알지 못해서 멀티 프로세스를 사용했으나, 이제 와서 생각하면 매우 운이 좋은 선택이었다.
멀티 프로세스와 멀티 스레드의 차이를 이해하기 위해서는 프로세스와 스레드의 차이부터 살펴볼 필요가 있다.
* 본격적인 설명 이전에 쉽게 차이를 말하자면
멀티 프로세스 : 파이썬 파일 여러개 동시에 실행
멀티 스레드 : 파이썬 파일내의 함수를 여러개 실행
이라고 대충 생각하고 넘어가보자!
1. 멀티 프로세스란? (부제 : 멀티 태스킹과는 다르다!)
앞에서 멀티 프로세스는 파이썬 파일을 여러개 동시에 실행시키는 것이라고 설명했는데,
사실 이건 반은 맞고, 반은 틀린 설명이다.(정확히는 멀티 태스킹을 의미하는 문장)
먼저 둘다 한정된 CPU 자원을 가지고 요구된 프로그램을 최대한 많이 처리하기 위해 지지고 볶는 작업이다.
굳이 포함관계를 다루자면
멀티 태스킹이 멀티 프로세스의 위에 있는 개념?이랄까?
기본적으로 CPU는 코어를 기반으로 연산작업이 수행된다.
I5 칩은 코어가 5개로, CPU 연산 (더하기 빼기, 데이터 입출력 등)을 동시에 5개 할 수 있다는 것을 의미한다.
그런데 만약 CPU 연산이 필요한 작업이 동시에 10개가 실행된다면?
이론상 노트북이 꺼져야 정상아닌가?
이걸 막기위한 방법이 멀티 태스킹이다.
10개의 작업이 있고, CPU 코어는 5개라면
각 작업마다 CPU 연산할 수 있는 시간을 지속적으로 할당해주는 것을 의미한다. (시분할 기법)
(* 코인 노래방에 시간 채워주는 느낌)
이를 통해 10개의 작업이 동시에 실행될 때,
실제로 동시에 처리되는 건 아니지만, '겉보기엔 동시에 처리되고 있는 것처럼 보이게' 만들 수 있는 것이다.
그럼 반대로,
코어는 5개인데, 내가 실행시키고 있는 프로그램들이 코어 하나로도 충분히 돌아갈 수 있다면?
나머지 코어 4개는 놀고 있는 것이다.
이때, "안그래도 시간 줄여야하는데, 감히 CPU가 놀아? 너 일로와서 일해"
라고 지시하는게 멀티 프로세싱이다.
그럼 이때 일을 시키는 방법은 뭘까?
가장 접근하기 쉬운 방법은 같은 실행 파일을 여러개의 터미널에서 실행시키는것이다. (다른 PID를 가지도록)
하지만 우리 똑똑한 개발자 선조들은 멀티프로세스라는 기능을 구현해놓았으니, 우리는 감사히 사용하면 된다.ㅎㅎ
(예제 코드는 다음 포스팅에서....)
2. 멀티 스레드란? (부제 : GIL이 뭔데?)
앞에서 멀티 프로세스는 파이썬 파일을 여러번 실행시키는 것이라고 대충 이해하고 넘어가되, 틀린 말이라는 것을 함께 언급했다.
이는 멀티 스레드와 멀티 프로세스의 차이점을 강조하기 위한 워딩이었는데,
두 기법의 가장 큰 차이는 '독립적인 메모리 공간의 유무'이고, 이 차이점을 이해하기 위해서는 스레드가 무엇인지 부터 알아야한다.
스레드란, 프로세스내의 실행 흐름 단위로,
쉽게 말해, 하나의 파이썬 파일에서 더하기 함수 -> 빼기 함수 -> 곱하기 함수가 순차적으로 호출된다고 했을 때
실행 시점부터 각각의 함수를 순차적으로 호출하며 프로세스가 종료될 때까지 끌고나가는 흐름이라고 보면 된다.
추가로, 파이썬에서는 기본적으로 GIL 매커니즘을 적용하고 있는데,
GIL 매커니즘이란, 한번에 하나의 스레드만 파이썬 객체에 접근할 수 있도록 제한하는 잠금 장치로
"파이썬 실행 파일의 흐름을 제어하는 건 딱 하나의 스레드임!!!"
을 의미한다.
이글을 보고 있는 사람이라면, 디버깅을 하면서 파이썬 객체에 순차적으로 접근하면서 알고리즘이 작동하는 것을 한번쯤은 확인해봤을 것이다.
이게 생각보다 큰 힌트인데, 다른 말로 표현하면 내가 작성한 코드의 객체는 사용될때까지 그 프로세스내에서만 사용될 수 있도록, 독립적으로 대기하고 있다는 것이다.
그럼 멀티스레드는?
말 그대로, 파일 실행 시점부터 종료될때까지 특정 작업 (함수 호출)이 동시에 처리되는 환경을 말한다.
근데 GIL이 깨지는건 아니다!!!!!
(* 멀티 태스킹과 같은 맥락으로 여러개의 스레드가 동시에 대기하되, GIL을 획득하는 스레드만 잠깐 동작하고 다른 스레드에게 GIL을 물려주는 방식으로 눈속임이 된다.)
그래서 결국 CPU 연산 등이 필요한 작업에 병렬처리가 필요할 때는 멀티스레드는 그닥 효율적이지 않다. (효율적인 것처럼 보이는 것 뿐)
하지만 I/O 작업 (파일 읽기/쓰기, 네트워크 통신 등)과 같은 운영체제, 하드웨어가 처리하는 작업의 경우 멀티 스레드로 메인 스레드에서 분리시킨다면 CPU 작업이 필요한 기타 작업과는 관계없이 병렬 처리될 수 있기에 성능을 끌어올릴 수 있다!
이제 슬슬 마무리를 해보자면...
우리는 멀티 프로세스와 멀티 스레드의 핵심적인 차이였던 '독립적인 메모리 공간의 유무'를 이해하기 위해 멀티 태스킹, 멀티 프로세스, 스레드, GIL에 대해 공부했다.
키워드 문장을 다시 정리하자면
1. 파이썬은 GIL 매커니즘을 따른다.
2. 따라서 하나의 파이썬 실행파일(프로세스)은 기본적으로 하나의 스레드가 담당한다.
3. 멀티스레드는 하나의 실행파일(프로세스)내에서 여러개의 스레드를 동작시키는걸 말한다.
4. 따라서 해당 실행파일에 있는 파이썬 객체를 여러개의 실행 흐름이 공유하여 사용한다.
5. 허나, 실제로 동작하는 스레드는 단 하나이다.
(절대 동시에 동작할 수 없다, 그렇게 보이기만 할뿐, 순서가 돌아가는 것 뿐이다!)
(* 멀티 태스킹과 비슷한 맥락)
이제 이로 인한 파급 효과를 정리하면 두 기법의 차이를 알 수 있다.
1. 메모리 공간:
- 멀티프로세스: 각 프로세스는 독립적인 메모리 공간을 가짐
- 멀티스레드: 모든 스레드가 같은 프로세스의 메모리 공간을 공유함
2. 안정성:
- 멀티프로세스: 한 프로세스에서 오류가 발생해도 다른 프로세스는 계속 실행됨
- 멀티스레드: 한 스레드의 문제가 전체 프로세스에 영향을 미칠 수 있음
3. 자원 소비:
- 멀티프로세스: 각 프로세스마다 별도의 메모리 할당으로 자원 소비가 큼
- 멀티스레드: 메모리를 공유하므로 상대적으로 자원 소비가 적음
4. 프로세스/스레드간의 통신 방식:
- 멀티프로세스: IPC(Inter-Process Communication) 필요 (큐, pool 등)
- 멀티스레드: 공유 메모리를 통해 쉽게 데이터 교환
5. 파이썬에서의 성능(GIL 영향):
- 멀티프로세스: GIL의 제약 없이 진정한 병렬 처리 가능
- 멀티스레드: GIL로 인해 CPU 바운드 작업 (이미지 처리, 텍스트 처리 등)에서 성능 향상 제한적 / IO 바운드 작업에 병렬 처리에 특화
읽어보면 알겠지만,
2번 부터 4번에 해당하는 안정성, 자원소비, 통신 방식은 핵심 차이점이었던 '독립적인 메모리 공간 유무'에 의한 것임을 확인할 수 있다.
이에 더해 5번에 해당하는 CPU 기반 성능 차이의 경우,
멀티 프로세스는 쓰지 않는 CPU 코어를 가져와 쓰는 방법이기 때문에 CPU 바운드 작업에 유리한 것이고,
멀티 스레드는 프로세스에 할당된 CPU 자원내에서 여러 실행 흐름이 순차적으로 GIL을 획득하면서 동작하는 것이기 때문에 CPU 바운드 작업에 불리할 수밖에 없다.
(* 당연히 이미 CPU 코어가 모두 쓰이고 있는 상태라면 멀티프로세스라고 하더라도 CPU 작업 능률에는 의미가 없다. -> 시분할 될뿐이다)
여기까지 멀티 프로세스와 멀티 스레드의 차이점에 대한 글을 정리했다.
이 글을 정리하면서 본인 스스로도 놓치고 있던 개념에 대해 정리할 수 있었고,
타인에게 쉽게 설명하기 위해 정리한다는 마인드로 적어내려가다보니 꽤나 뿌듯하다 ㅎㅎ
본인은 그저 병렬처리가 해보고 싶어서 선 구현, 후 이해한 케이스이지만,
지금 이 글을 읽는 분들은 더 빠르게 이해하고, 응용할 수 있기를 바라며...
ㄱㅊㅁ_ㅇㅈ