스레드
예전의 프로세스는 단일 실행 스레드(single thread of execution)을 가졌다면 지금의 프로세스는 여러 개의 스레드를 가져 여러 개의 실행 흐름을 가지게 되었다. 예전에는 프로세스가 여러 개의 실행 흐름을 가지기 위해 새 프로세스를 생성했다. 하지만 프로세스를 생성하는 건 많은 시간과 자원이 요구되는 작업이며 같은 일을 하는 프로세스를 여러 개 두는건 매우 비효율적이다. 때문에 경량화된(light-weight) 프로세스인 스레드가 등장했다. 스레드는 원래 실타래, 프로그램 실행 흐름을 의미하는 용어였다.
- 멀티스레딩 시스템에서 CPU를 점유하는 단위는 프로세스가 아닌 스레드이다.
- 스레드는 경량화된 프로세스(Light-Weight Process, LWP)이다.
- 스레드는 스레드 ID, 프로그램 카운터(PC), 레지스터 집합, 스택으로 구성된다.
- 스레드는 자동으로 그들이 속한 프로세스의 자원(코드 영역, 데이터 영역, 힙 영역, 파일)을 공유한다.
멀티스레딩의 장점
- 응답성(responsiveness) : 프로그램 수행이 계속되도록 함으로써 사용자에 대한 프로그램 응답성을 증가시킨다.
- 리소스 공유(resource sharing) : 프로세스가 공유 메모리와 메시지 전달 기법을 통해서만 자원을 공유할 수 있다. 이러한 기법은 응용 프로그래머의 부담을 높인다. 하지만 스레드는 자동으로 그들이 속한 프로세스의 자원을 공유한다.
- 경제성(economy) : 프로세스는 자체적으로 자원을 가지기에 프로세스 생성에는 비용이 많이 든다. 하지만 스레드는 자신이 속한 프로세서의 자원을 공유한다. 때문에 스레드를 생성하고 스레드 간의 문맥 교환하는 것이 더욱 경제적이다.
- 규모 적응성(scalability) : 멀티 스레드는 멀티 프로세서 시스템에서 이점을 가진다.
멀티 코어 시스템에서의 스레드
멀티코어 시스템에서 코어 개수만큼 스레드를 병렬로(parallel) 실행하며 각 cpu 코어는 매우 빈번하게 작업(스레드)를 전환하며 실행해 스레드를 동시에(concurrently) 실행한다.
멀티 코어 시스템에서의 도전 과제
멀티코어 시스템은 운영체제 설계자에게 여러 코어를 활용하는 스케줄링 알고리즘을 개발하도록 압박을 주며 응용 프로그래머에게는 다중 스레드 프로그램을 설계하도록 압박을 준다. 프로그래머는 멀티 코어 시스템에서 프로그래밍 하기 위해 아래의 도전 과제를 해결해야한다.
- 태스크 인식(identifying tasks) : 프로그램을 분석해 독립된 병행 가능 태스크(스레드)로 나누는 작업, 태스크는 서로 독립적이고 따라서 개별 코어에서 병렬 실행될 수 있다.
- 균형(balance) : 전체 작업에 균등한 기여도를 가지도록 태스크를 나눠야한다.
- 데이터 분리(data spliting) : 태스크가 나누어진것처럼, 태스크가 접근하는 데이터 또한 개별 코어에서 사용할수 있도록 나눠야한다.
- 데이터 종속성(data dependency) : 태스크가 접근하는 데이터는 둘 이상의 태스크 사이에 종속성이 없는지 검토, 종속성이 존재한다면 동기화가 필요하다.
- 시험 및 디버깅(testing and debugging) : 프로그램이 멀티 코어 시스템에서 병렬로 실행되면 다양한 실행 경로가 존재하기에 디버깅과 테스팅이 매우 어렵다.
암달의 법칙
암달의 법칙(Amdahl's Law)은 순차 실행 구성 요소와 병렬 실행 구성 요소로 이루어진 응용 프로그램에 추가의 계산 코어를 더했을때 얻을 수 있는 성능 이득을 나타내는 공식이다. N은 코어의 개수, S는 순차적으로 실행되어야만 하는 구성 요소, Speedup은 성능 이득이다.
암달의 법칙에서 재밌는 점은 N이 무한대에 가까워지면 성능 이득은 1/S에 수렴한다. 즉 응용 프로그램의 순차 실행 부분이 50%를 차지한다면 코어를 아무리 늘려도 성능 이득은 2배를 넘지 못한다. 따라서 S가 클수록 아무리 코어가 많아도 성능 향상을 기대하지 못한다는 걸 시사한다.
암묵적 스레딩
스레드를 응용 프로그램에서 직접 생성, 관리하는 것은 응용 프로그래머의 부담을 높인다. 때문에 스레드의 생성과 관리를 컴파일러 또는 런타임 라이브러리에게 맡기는 암묵적 스레딩(Implicit Threading)이 점점 사용되고 있다. 다음 4가지 암묵적 스레딩 기법이 있다.
- 스레드 풀
- Fork Join 모델
- OpenMP
- GCD (Grand Central Dispatch)
스레드 풀
스레드 풀이 필요한 이유를 웹서버에서 살펴보자. 웹서버는 요청을 받으면 요청을 처리하기 위해 스레드를 만든다. 하지만 스레드 생성에는 프로세스 생성 만큼은 아니지만 시간이 필요하다. 특히 요청을 다 처리하면 스레드를 폐지한다는 점에서 스레드 생성 시간은 더욱 낭비이다. 그리고 서버 자원의 한계로 스레드 생성 개수의 한계를 정해야한다. 만약 요청마다 스레드를 만든다면 서버가 다운될 수 있다. 위 문제를 해결하기 위해 스레드 풀을 사용한다.
스레드 풀의 기본 아이디어는 프로세스를 시작할 때 아예 일정한 수의 스레드들을 미리 풀로 만들어두는 것이다. 이 스레드들은 대기 상태에 있다가 작업을 받으면 해당 작업을 수행한다.
'Computer Science > OS' 카테고리의 다른 글
[OS - 7] 프로세스 동기화 (0) | 2023.05.25 |
---|---|
[OS - 6] CPU 스케줄링 (0) | 2023.05.03 |
[OS - 4] IPC (0) | 2022.11.21 |
[OS - 3] 프로세스 (0) | 2022.11.15 |
[OS - 2] 운영체제 개요 (2) (0) | 2022.11.09 |