[CS/컴퓨터구조] 프로세스와 쓰레드, 파이썬의 병렬 처리
프로세스(Process)
본래 실행중인 프로그램 자체를 의미하는 용어지만, 프로그램의 실행 단위를 말하기도 한다. 하나의 프로그램을 실행한다는 것은 하나의 프로세스가 진행된다는 것과 같은 의미이며, 이전에는 이것이 유일한 프로그램의 실행 단위였으나 더 작은 의미의 실행 단위인 쓰레드 개념이 등장했다. 이전에는 컴퓨터가 한 번에 하나의 프로세스만을 처리할 수 있었으나, 다양한 프로세스 스케줄링 기법을 통해 여러 프로세스를 동시에 수행하는 것이 가능해졌다.
쓰레드(Thread)
하나의 프로세스 내에서 실행되는 흐름의 단위로, 하나의 프로세스는 최소 한 개의 쓰레드를 가진다. 하나의 프로세스 내에서 여러 개의 쓰레드를 생성하는 경우, 작업 수행을 위한 스택은 각각 별도로 가지지만 메모리는 공유하게 된다. 은행(프로세스) 안의 여러 개의 창구(쓰레드), 공장(프로세스) 안의 여러 개의 라인(쓰레드)이라고 이해해볼 수 있다.
멀티 프로그래밍(Multi-Programming)
하나의 프로세서(CPU)가 여러 개의 프로세스에 동시에 접근하도록 하는 것을 말한다. 가령 1000장짜리 인쇄를 눌러놓고 인터넷 검색을 하고 싶은데 인쇄가 끝나길 기다려야 한다면? 과거의 컴퓨터는 실제로 CPU가 하나의 프로세스가 종료될 때까지 기다려야 했다고 한다. 일반적으로 프로세스는 CPU를 한차례 사용(CPU burst)하고 I/O를 한차례 사용(I/O burst)하는 주기를 반복하는데, I/O를 사용하는 주기에서는 CPU를 사용하지 않는다는 점을 이용해 한 프로세스를 실행 가능한 시점까지 실행하고, I/O 등 CPU를 사용하지 않는 작업을 할 때는 다른 프로세스를 실행하는 방법으로 CPU 활용을 극대화하는 방법으로 멀티 프로그래밍이 가능하다.
위 예를 기준으로 생각하면 CPU의 작동이
인쇄할 데이터 일부 불러오기→ 인쇄 명령 → 프린터가 인쇄하는 동안 다른 프로세스 실행 → 반복
의 느낌으로 진행될 것이다.
멀티 프로세싱(Multi-Processing)
하나가 아닌 여러 개의의 프로세서(CPU)를 활용해 동시에 여러 개의 프로세스를 처리하는 것을 말한다. CPU1이 1번 프로세스를, CPU2가 2번 프로세스를 담당하는 방식이 아니라 하나의 프로세스를 n개의 CPU가 나누어 병렬적으로 처리하는 것을 의미한다. 프로세스 처리 속도가 빨라질 뿐 아니라, CPU 자체의 결함이나 고장에 robust해지는 효과도 있다. 다만 프로세서간에 task를 주고 받는 경우(Context Switching) IPC(Inter Process Communication)가 일어나기 때문에, 캐싱 메모리를 초기화 한다는 점에서 비용이 크다.(멀티쓰레딩에 비해 상대적으로 느림)
멀티 쓰레딩(Multi-Threading)
하나의 프로세스 내에 여러 개의 쓰레드를 두어 작업을 병렬처리 하는 것을 말한다. 각 쓰레드는 작업 처리를 위한 stack 영역 외의 것들을 하나의 프로세스 내에서 공유하기 때문에, 메모리와 시간 면에서 효율적이다(Context Switching이 빠르다). 하지만 장점인 동시에 단점인 것이, 여러 개의 쓰레드가 동일한 메모리 공간에 동시에 접근할 수 있게 되므로, 실행 순서의 차이 등으로 의도하지 않은 결과를 얻는 등의 문제가 생길 수 있기 때문에 보다 세심한 작업을 필요로 한다. (참고)
파이썬의 멀티쓰레딩과 멀티프로세싱
결론부터 말하면, 파이썬은 본래 의미의 멀티쓰레딩은 지원하지 않으며, 본래 의미의 병렬 분산처리를 수행하기 위해서는 멀티 프로세싱을 이용해야 한다. 이는 GIL(Global Interpreter Lock)이라는 파이썬 본연의 정책 때문인데, 이유는 언어를 만든 사람에게 따져봐야 알겠으나 멀티쓰레딩을 허용했을 때 나처럼 '세심하지 못한' 사용자가 무수히 생산해낼 수 있는 버그들을 아예 사전에 방지해둔 것으로 이해했다.
threading 모듈의 Thread 함수를 이용해 여러 개의 쓰레드를 할당하고 동시에 실행시켜 볼 수 있으나, 이때 일어나는 동작은 실제 각 쓰레드들이 동시에 작동되는 멀티쓰레딩이 아닌 위에 언급한 멀티 프로그래밍으로, CPU에 의해 이전 쓰레드가 진행하던 프로세스가 I/O 과정을 진행하는 경우 다음 쓰레드에 입력된 프로세스가 CPU를 점유하는 형태다. 즉, 여전히 CPU가 동시간에 처리하는 쓰레드는 1개 뿐이다.
대신 여러 개의 CPU를 보유하고 있다면 multiprocessing 모듈을 활용해 병렬 처리를 구현할 수 있으며, 구현 방식 자체는 threading 모듈과 거의 유사하다고 한다. 이는 추후에 다뤄보도록 하겠다.