사람이 벽돌을 올리는 작업을 생각해보자, 굳이 한 손으로 벽돌을 올리는 것보다는 두 손을 이용해서 벽돌을 위로 올린다면 작업능률 또한 2배로 올라갈 것이다. Thread 컨셉 또한 이와 다르지 않다.
우선 우리는 Process에 대해 알고있다. 1~100 까지 더해야 하는 상황일때 process를 10개 만들어서 각 prcoess가 1~10까지,11~20, .. ,91~100 까지를 각자 더해주고 그 결과값을 더해준다면 단일 process 계산에 비해서 성능은 10배로 올라갈 것이다. 하지만, 이는 사실 굉장히 비효율적이다. 왜 그럴까?
첫 번째 예시를 잘 생각해보자. 각 process가 자신의 고유한 영역(주소 공간)이 정해져 있기 때문에 데이터를 주고 받기 위해서는 system call이 발생하거나 socket 인터페이스를 통한 데이터 송수신이 필요하다 ( e.g. socket, message queue,공유 메모리 etc ...). 즉, 성능이 나빠지게 될 수도 있다.
하지만 병렬적인 연산이야말로, 사실 근본적인 성능 향상의 해결책이다. 그럼 어떻게 해야 병렬적인 연산을 효율적으로
처리할 수 있을까? 하나의 process내에 cpu의 최소 연산단위인 Thread를 도입한다.
이제부턴 Thread가 스케쥴링의 단위가 된다.(스케쥴링은 Context switching에서 더욱 자세히 다루겠다)
다음은 우리가 Process에 기반하여 주소 공간을 생각했을때의 process 주소 공간의 구조이다.
아래는 Thread에 기반하여 주소 공간을 생각했을때 정의된 process 주소 공간의 구조이다.
그림만 보고는 조금 이해가 어려울 테니 C코드와 함께 살펴보자.
int main(){
f1(g(x));
f2(h(t));
}
Process에 f1(g)와 f2(h)가 stack공간을 차지하고 있다. 이들은 각자의 program counter와 stack pointer를 가진다.
각자의 영역이 overwrite되지 않기 위해 OS는 process 주소 공간을 조율하여 각 thread에게 할당하여준다.
자 그러면 Thread가 병렬 computing에 효율적이란 것은 알았다. 그렇다면, Thread의 생성은 누가 담당할 것인가?
User-level Thread : 각 process에 thread를 관리하는 table이 존재하지만 OS가 process 내부의 thread를 관리할 수 없다.
Kernel Thread: Process의 thread의 생성과 관리가 syscall을 통한 커널영역을 통해 이루어진다.
병렬적인 computing을 위한 process와 thread를 알아보았다. process 방식과 thread 방식은 각자 일장 일단이 존재한다. 우선 process의 장점은, 각자의 주소공간이 분리 되어있어 강력한 보안을 제공한다는 것이다. 그렇기 각 process는 독립적으로 다뤄질 수 있다. 하지만, parallel programming에는 불리한 부분이 존재한다.
Thread의 경우 같은 주소공간을 공유하고 있기에 parallel programming에 더욱 유리하다.이와 같이, 프로그램의 목적이나 그 목표에 따라 적절히 두 가지 기법을 혼합하여 사용하면 될 것 같다.