스레드는 CPU 사용의 기본 단위이며, 스레드ID, 프로그램 카운터(PC), 레지스터 집합, 스택으로 구성됩니다. 스레드는 같은 프로세스에 속한 다른 스레드들과 코드, 데이터 섹션, 열린 파일이나 신호와 같은 OS 자원들을 공유합니다.
서버에게 서비스 요청이 들어오면, 프로세스는 그 요청을 수행할 별도의 프로세스를 생성합니다. 이러한 방법은 스레드가 대중화되 전에는 매우 보편적이었습니다. 하지만 프로세스 생성 작업은 많은 시간을 소비하고 많은 자원을 필요로 하는 작업입니다. 또한 새 프로세스가 해야 할 일이 기존 프로세스가 하는 일과 동일하다면 많은 오버헤드를 감수해가며 이 작업을 해야할 이유가 있을까요? 이 같은 방법보다 프로세스 안에 여러 스레드르르 만드는 것이 더 효율적입니다. 웹 서버가 멀티 스레드화 되면, 서버는 클라이언트의 요청을 listen하는 별도의 스레드를 생성합니다.
대부분의 OS 커널도 일반적으로 멀티 스레드입니다. 예를 들어 linux시스템에서 시스템을 부트하는 동안 여러 커널 스레드가 생성됩니다. 이 스레드들은 각각 장치 관리, 메모리 관리 또는 인터럽트 처리와 같은 특정 작업을 수행합니다. ps -ef 명령을 사용하여 실행 중인 linux 시스템에서 커널 스레드를 확인할 수 있습니다. 이를 통해 kthread(pid=2, 커널스레드)가 보이여 이 스레드는 다른 모든 커널 스레드의 부모 역할을 하는 스레드입니다.
멀티 코어 프로그래밍은 하나의 컴퓨터에 여러 개의 프로세서(코어)가 존재하면서, 이를 활용하여 작업을 처리하는 방식입니다. 이는 병행성과 병렬성을 모두 활용하는 방식으로, 하나의 작업을 여러 개의 작은 작업으로 분할하여, 각각의 코어에서 병렬적으로 실행하면서 더 빠르게 처리할 수 있습니다.
병행성은 논리적 개념에 가깝습니다. 실제로 동시에 실행되지 않더라고 그렇게 작동하는 것처럼 느껴지는 것입니다. 하나의 프로세서에서 여러 개의 작업을 동시에 처리하는 것이 아니라, 작업 간에 번갈아 가며 실행되어 보이게 만듭니다. 이는 스레드(Thread)나 프로세스(Process)를 사용하여 구현됩니다. 병행성의 예시로는 Mutex, DeadLock이 있습니다.
병렬성은 실제로 동시에 작업이 처리되는 물리적 수준의 개념입니다. 여러 개의 프로세서(CPU)나 코어(Cores)를 사용하여 작업을 분할하고 병렬적으로 실행합니다. 이는 멀티프로세싱(Multiprocessing)이나 GPU(Graphics Processing Unit)를 사용하여 구현됩니다.
다중 처리기 및 다중 코어 아키텍처가 출현하기 전에 대부분의 컴퓨터 시스템에서는 단일 프로세스만 존재했으며 CPU 스케줄러는 프로세스 간에 빠르게 전환해 각 프로세스가 진행되도록 하여 병렬성의 환상을 제공했습니다. 즉, 병렬성(Parallelism) 없이 병행성(Concurrency)을 가질 수 있었습니다.
그러나 처리해야할 데이터가 많아지고 성능의 향상을 위하여 병렬성은 빼놓을 수 없는 개념이었습니다.
태스크 인식(Identifying tasks)
응용 프로그램을 분석하여 병행 가능 태스크로 나눌 수 있는 영역을 찾아내는 작업이 필요합니다. 태스크는 서로 독립적이고 개별 코어에서 병렬적으로 실행될 수 있어야 합니다.
균형(Balance)
병렬적으로 실행될 수 있는 태스크를 찾아 냈다면 적체 작업에 균등한 기여도를 가지도록 나누는 작업이 필요합니다. 예를 들어, 1번 태스크가 2번 태스크에 비해 기여도가 적은 작업을 가지고 있다면 별도의 코어를 사용하는 것은 비효율적일 수 있기 때문에 각각의 기여도에 맞게 코어를 분배하던지, 각각의 태스크들이 최대한 비슷한 기여도를 가지게 하여 코어 또한 균등하게 배분하는 방법을 고려해야 합니다.
데이터 분리(Data spliting)
응용 프로그램이 독립된 태스크로 나뉘는 것처럼, 태스크가 접근하고 조작하는 데이터 또한 개별 코어에서 사용할 수 있도록 나누어져야 합니다.
데이터 종속성(Data Dependency)
동기화 문제와 관련된 이슈입니다. 두 태스크가 한 데이터에 접근 및 작업하게 된다면 그 두 태스크는 서로가 작업한 데이터에 대하여 종속성이 생기게 됩니다. 프로그래머는 이러한 종속성을 수요할 수 있는지 확인하고 태스크의 작업 수행을 잘 동기화해야합니다.
시험 및 디버깅(testing and debugging)
프로그램이 다중 코어에서 병렬로 실행될 때, 다양한 실행 경로가 존재할 수 있습니다. 그런 병행 프로그램을 시험하고 디버깅하는 것은 싱글 스레드 어플리케이션을 테스트하고 디버깅하는 것보다 훨씬 어렵습니다.
다대일 모델(Many to One Model)
여러개의 user level 스레드를 하나의 kernel 스레드로 사상하는 모델입니다. 멀티 프로세스, 코어가 대부분인 현대 컴퓨터 시스템에서 시스템의 이점을 살릴 수 없기 때문에 거의 존재하지 않는 모델입니다.
일대일 모델(One to One Model)
각각의 user level 스레드를 1대1로 kernel 스레드로 사상하는 모델입니다. 하나의 스레드가 봉쇄적 시스템 콜을 호출하더라도 다른 스레드가 실행될 수 있기 때문에 다대일 모델보다 더 많은 병렬성을 제공합니다. 또한 멀티 프로세스, 코어 환경에서 멀티 스레드가 병렬로 수행되는 것을 가능하게 한 모델입니다. 이 모델의 유일한 단점은 user level 스레드를 만들기 전 맵핑되는 커널 스레드를 먼저 만들어야 하며 많은 수의 커널 스레드가 시스템 성능에 영향을 줄 수 있다는 것입니다. Linux, Windows가 해당 모델을 채택했습니다.
다대다 모델(Many to Many Model)
여러 user level 스레드를 여러개의 kernel 스레드로 맵핑한 모델입니다. 다대다 사상은 멀티플렉싱을 통해 구현되어 있습니다. 이러한 방식으로 인해, 다중 스레드 프로그래밍에서 발생하는 스레드 생성과 관리에 대한 부담을 줄이고 성능을 향상시킬 수 있습니다.
언뜻 생각하기에는 가장 효율적이고 융통성있는 모델 같아 보이지만 실제로 구현하기가 어렵습니다. 또한 대부분의 시스템에서 처리 코어 수가 증가함에 따라 커널 스레드 수를 제한하는 것이 별로 중요하지 않게 되었습니다. 결과적으로 대부분의 OS는 일대일 모델을 사용합니다.
Amdahl's Law는 순차 실행 구성요소와 병렬 실행 구성요소(순차 + 병렬)로 이루어진 응용 프로그램에 추가의 계산 코어를 더했을 때 얻을 수 있는 잠재적인 성능 이득을 나타내는 공식입니다.
Speedup(S) = 1 / [(1 - p) + (p / n)]
여기서 p는 병렬로 실행할 수 있는 부분의 비율을 나타내며, n은 프로세서 수를 나타냅니다. Speedup(S)는 병렬 처리 시스템에서 실행 시간이 단일 처리 시스템과 비교하여 얼마나 빨라졌는지를 나타내는 지표입니다.
예를 들어 75%의 병렬 실행 구성요소와 25% 순차 실행 구성요소를 가진 응용 프로그램이 있다고 가정합니다. 이 응용 프로그램을 코어가 2개인 시스템에서 실행시킬 경우, 약 1.6배의 속도 향상을 얻을 수 있습니다. 만일 2개의 코어를 추가한다면(코어 총 4개) 속도는 2.28배 빨라집니다.
그림에서 예시를 들어보면, 응용 프로그램의 50%가 병렬 실행이고 나머지 50%가 순차 실행이라면 코어를 아무리 추가한다고 하더라도 최대 2.0배 이상의 속도 향상은 얻을 수 없습니다. 만약 90%가 병렬 실행이고 10%가 순차 실행이라면, 그래프의 초록색 부분처럼, 코어를 추가할 시 얻을 수 있는 속도 향상은 가파르게 증가하다 20배에 수렴하게 됩니다.
Amdahl's law는 병렬 처리 시스템의 속도 향상을 제한하는 데 사용됩니다. 법칙은 병렬 처리 시스템에서 병렬화할 수 있는 부분이 일부인 경우, 추가 프로세서를 사용하여 시스템의 속도를 더욱 빠르게 만들어도 한계가 있다는 것을 보여줍니다. 즉, p가 작을 경우, 추가 프로세서를 사용하여 성능 향상을 얻는 것이 한계적일 수 있습니다.
따라서, 병렬 처리 시스템에서 성능을 더욱 향상시키려면, 병렬화할 수 있는 부분을 최대한 많이 찾아내어 p값을 높이는 것이 중요합니다. 또한, 법칙을 사용하여 시스템의 속도 향상을 예측하면서 추가 프로세서를 사용하여 성능을 개선하는 데 필요한 비용과 효과를 평가할 수 있습니다.
스레드 라이브러리는 프로그래머에게 스레드를 생성하고 관리하기 위한 API를 제공합니다.
스레드 라이브러리를 구현하는 데에는 주된 두 가지 방법이 있습니다.
커널의 지원 없이 완전히 사용자 공간에서만 라이브러리를 제공하는 것
라이브러리를 위한 모든 코드와 자료구조는 사용자 공간에만 존재하게 됩니다. 라이브러리의 API를 호출하는 것은 시스템 콜이 아니라 사용자 공간의 지역 함수를 호출하게 된다는 것을 의미합니다.
OS에 의해 지원되는 커널 수준 라이브러리를 구현하는 것
라이브러리를 위한 모든 코드와 자료구조는 커널 공간에만 존재하게 됩니다. 라이브러리 API를 호출하는 것은 커널 시스템 콜을 부르는 결과를 낳습니다.
대표적인 라이브러리들로는 POSIX Pthread, Windows, Java가 있습니다. POSIX 표준안의 스레드 확장판인 Pthreads는 사용자 또는 커널 수준 라이브러리로서 제공될 수 있습니다. Windows 스레드 라이브러리는 Windows 시스템에서 사용 가능한 커널 수준 라이브러리입니다. Java Thread API는 Java프로그램에서 직접 스레드 생성과 관리를 가능하게 합니다. 그러나 대부분의 JVM 구현은 호스트 운영체제에서 실행되기 때문에 Java Thread API는 통상 호스트 시스템에서 사용 가능한 스레드 라이브러리를 이용하여 구현됩니다. Windows 시스템에서 Java 스레드는 Windows API를 사용하여 구현된다는 것을 의미합니다. UNIX, Linux 및 macOS 시스템에서는 통상 Pthreads를 사용합니다.
비동기 스레딩은 부모 스레드가 자식 스레드를 생성한 후 자신의 실행을 재개하여 부모와 자식 스레드가 서로 독립적으로 병행하게 실행됩니다. 스레드가 독립적이기 때문에 스레드 사이의 데이터 공유는 거의 없습니다. 또한 스레드를 생성하고 관리하는 부분을 사용자 코드에서 처리합니다. 이 방식은 스레드 생성과 관리에 대한 자유도가 높고, 성능이 좋은 장점이 있습니다. 그러나, 스레드 생성과 관리에 대한 부담이 크기 때문에, 사용자 코드에서 적절한 동기화(synchronization)를 구현하지 않으면, 다중 스레드 프로그래밍에서 발생할 수 있는 문제(경쟁 상태, 데드락 등)가 발생할 수 있습니다.
동기 스레딩은 부모 스레드가 하나 이상의 자식 스레드를 생성하고 자식 스레드 모두가 종료할 때까지 기다렸다가 자신의 실행을 재개하는 방식을 말합니다. 부모가 생성한 자식 스레드들은 병행하게 실행됩니다. 통상 동기 스레딩은 스레드 사이의 상당한 양의 데이터 공유를 수반합니다. 예를 들어 부모 스레드는 자식들이 계산한 결과를 통합할 수 있습니다. 동기 스레딩은 스레드 생성과 관리를 스레드 라이브러리에서 처리하는 방식입니다. 이 방식은 스레드 생성과 관리에 대한 부담을 스레드 라이브러리에서 처리하기 때문에, 사용자 코드에서는 스레드 생성과 관리에 대한 부담이 적습니다. 그러나, 스레드 라이브러리에서 지원하는 스레드 생성과 관리 방식에 대한 제약이 있기 때문에, 사용자 코드에서 필요한 기능을 모두 구현할 수 없을 수도 있습니다.
멀티 코어의 지속적 성장에 따라 수백 또는 수천 개의 스레드를 가진 응용 프로그램들이 등장하기 시작했습니다. 그에 따라 프로그래머는 위에서 설명한 프로그래밍 도전 과제 뿐만 아니라 설계, 그 외의 여러 어려움을 극복해야 합니다. 이러한 어려움을 극복하고 병행 및 병렬 응용 프로그램의 설계를 도와주는 한 가지 방법은 스레딩의 생성과 관리 책임을 프로그래머로부터 컴파일러와 실행시간 라이브러리에게 넘겨주는 것입니다.
암묵적 스레딩이라고 불리는 이 전략은 점점 더 널리 사용되고 있습니다.이 방법의 장점은 개발자는 병렬 작업만 식별하면 되고 라이브러리는 스레드 생성 및 관리에 대한 특정 세부 사항을 결정한다는 것입니다.
서버가 새로운 요청을 받을 때마다 새로운 프로세스를 만드는 것보다 스레드를 만드는 것이 더 진보된 방법이지만 아직 여러 문제를 가지고 있습니다.
서비스할 때마다 스레드를 생성하는데 소요되는 시간입니다. 스레드는 해당된 작업이 끝나면 바로 폐기된다는 점을 고려하면 요청마다 스레드를 생성하는 건 문제입니다.
모든 요청마다 새 스레드를 만들어 서비스한다면 시스템에서 동시에 실행할 수 있는 최대 스레드 수가 몇 개까지 가능할 수있는 것인지 한계를 정해야한다. 스레드를 무한정 만들면 언젠가는 CPU시간, 메모리 공간 같은 시스템 자원이 고갈될 것입니다.
이러한 문제를 해결할 수있는 방법 중 하나가 스레드 풀입니다.
스레드 풀의 기본 아이디어는 프로세스를 시작할 때 일정한 수의 스레드들을 미리 풀로 만들어두는 것입니다. 평소에는 가만히 기다리다 서버에 요청이 들어오면 새로운 스레드를 만드는 것이 아니라 스레드 풀 안에 있는 스레드가 활동을 시작하는 방법입니다. 풀에 사용 가능한 스레드가 없으면 사용 가능한 스레드가 생길 때까지 작업이 대기됩니다. 스레드가 작업을 완료하면 풀로 돌아가서 다음에 들어올 작업에 대해서 대기합니다. 풀에 제출된 작업을 비동기적으로 실행할 수있는 경우 스레드 풀이 제대로 작동됩니다.
스레드 풀에 있는 스레드의 개수는 CPU 수, 물리 메모리 용량, 동시 요청 클라이언트 최대 개수 등을 고려하여 정해질 수 있습니다. 풀의 활용도를 보며 동적으로 풀의 크기를 바꾸어줄 수도 있습니다. 예를 들어, 시스템 부하가 적을 때에는 더 작은 풀을 유지하도록 함으로써 메모리 등의 소모를 더 줄일 수 있습니다.
Fork-Join은 스레드 생성 전략 중 하나입니다. Fork-join은 병렬 처리를 위해 사용되는 방식으로, 작업을 재귀적으로 분할하고 각각의 작은 작업을 병렬적으로 실행한 후, 결과를 다시 모아서 원래 작업을 완료하는 방식입니다. 이 방식은 작업을 더 작은 작업으로 분할하면서, 각 작업을 병렬적으로 실행하여 전체 작업을 빠르게 처리할 수 있도록 합니다.
Fork-join 방식에서는 작업을 더 이상 분할할 수 없을 때까지 분할하며, 각 작업은 스레드 풀(Thread pool)에서 실행됩니다. 스레드 풀은 미리 생성된 스레드들로 구성되어 있으며, 작업이 실행될 때마다 해당 스레드를 할당하여 작업을 처리합니다. 이 방식으로 인해, 스레드 생성과 관리에 대한 부담을 줄일 수 있고, 효율적인 병렬 처리가 가능합니다.
다중 스레딩이 단일 스레드 솔루션보다 더 나은 성능을 제공하는 세 가지 프로그래밍 예제를 제시하라.
웹 서버
웹 서버는 동시에 여러 클라이언트 요청에 응답해야 하기 때문에 멀티 스레드가 필요합니다. 단일 스레드 웹 서버의 경우, 클라이언트 요청에 대한 응답이 완료되기 전까지 다음 요청을 처리할 수 없습니다. 그러나 멀티 스레드 웹 서버는 여러 클라이언트 요청을 동시에 처리할 수 있기 때문에, 대기 시간을 최소화하고 더 빠른 응답 시간을 제공할 수 있습니다.그래픽 사용자 인터페이스
그래픽 사용자 인터페이스 (GUI)는 많은 이벤트를 처리해야 합니다. 이벤트는 마우스 클릭, 키보드 입력, 창 이동 등 다양한 작업을 수행합니다. 단일 스레드 GUI의 경우, 하나의 이벤트가 처리될 때까지 다른 이벤트를 처리할 수 없습니다. 멀티 스레드 GUI는 이벤트를 처리하는 동안 다른 이벤트를 처리할 수 있기 때문에, 사용자 경험을 향상시키고 반응성을 높일 수 있습니다.데이터베이스 서버
데이터베이스 서버는 동시에 여러 클라이언트 요청에 응답해야 하기 때문에 멀티 스레드가 필요합니다. 단일 스레드 데이터베이스 서버의 경우, 하나의 클라이언트 요청이 처리되기 전까지 다른 클라이언트 요청을 처리할 수 없습니다. 그러나 멀티 스레드 데이터베이스 서버는 여러 클라이언트 요청을 동시에 처리할 수 있기 때문에, 대기 시간을 최소화하고 더 높은 처리량을 제공할 수 있습니다.
Amdahl의 법칙을 사용하여 (a) 2개의 처리 코어와 (b) 4개의 처리 코어에 대해 60%의 병렬 구성요소를 가진 응용 프로그램의 속도 향상 이득을 계산하라.
Amdahl의 법칙은 병렬화 가능한 작업의 비율과 프로세서 개수에 따라 속도 향상 이득을 계산하는 공식입니다.
Amdahl의 법칙:
Speedup = 1 / (1 - P + P/N)
여기서 P는 프로그램을 병렬화할 수 있는 비율을 나타내고, N은 프로세서의 개수입니다.
(a) 2개의 처리 코어의 경우:
P = 60%, N = 2
Speedup = 1 / (1 - 0.6 + 0.6/2) = 1 / 0.7 = 1.43
따라서, 2개의 처리 코어를 사용하는 경우 속도 향상 이득은 43%배입니다.
(b) 4개의 처리 코어의 경우:
P = 60%, N = 4
Speedup = 1 / (1 - 0.6 + 0.6/4) = 1 / 0.55 = 1.82
따라서, 4개의 처리 코어를 사용하는 경우 속도 향상 이득은 82%배입니다.
4.1절에 설명된 다중 스레드 웹 서버는 작업 병렬 처리인가 혹은 데이터 병렬 처리인가?
데이터 병렬 처리는 동이란 데이터의 부분 집합을 다른 컴퓨팅 코어에 분산시키고 각 코어에서 동일한 연산을 수행한다. 작업 병렬 처리는 여러 코어에 데이터가 아니라 작업을 분산시킨다. 각 작업은 고유한 연산을 실행한다.(p.216)
4.1절에 설명되어 있는 멀티 스레드 웹 서버는 데이터의 부분집합이 아닌 이미지, 텍스트 등 태스크(작업) 단위로 설명되어 있습니다. 따라서 작업 병렬 처리입니다.
사용자 수준 스레드와 커널 수준 스레드의 2가지 차이점은 무엇인가? 한 유형의 스레드가 다른 유형의 스레드보다 유리한 상황은 언제인가?
생성
- 사용자 수준 스레드는 응용 프로그램에서 직접 생성됩니다.
- 커널 수준 스레드는 운영 체제에서 생성됩니다.
동기화
- 사용자 수준 스레드는 스레드 간 동기화를 위한 기능을 제공하지 않습니다.
- 커널 수준 스레드는 스레드 간 동기화를 위한 기능을 제공합니다.
중단
- 사용자 수준 스레드는 중단되면 다른 사용자 수준 스레드를 실행할 수 있습니다.
- 커널 수준 스레드는 중단되면 다른 스레드를 실행할 수 없습니다.
한 유형의 스레드가 다른 유형의 스레드보다 유리한 상황은 다음과 같습니다.
사용자 수준 스레드는 스레드 간 전환 비용이 적으므로, 스레드가 빈번히 생성되고 소멸되는 경우 유리합니다.
커널 수준 스레드는 운영 체제에서 스케줄링되기 때문에, 다중 프로세서에서 병렬 처리를 할 수 있습니다. 또한, 스레드 간 동기화가 필요한 경우에는 커널 수준 스레드가 유리합니다
커널 수준 스레드 사이에서 문맥 교환(Context Switching)을 위해 커널이 해야 할 일을 설명하라.
현재 실행 중인 스레드의 상태를 저장
현재 스레드가 실행을 멈추는 지점의 프로그램 카운터(Program Counter) 값을 저장합니다.
현재 스레드의 레지스터 값, 스택 포인터 등의 상태를 저장합니다.다음 실행할 스레드의 상태를 복원
다음 실행할 스레드의 프로그램 카운터 값을 로드합니다.
다음 스레드의 레지스터 값, 스택 포인터 등의 상태를 복원합니다.스케줄링 결정
다음 실행할 스레드를 선택하기 위해 스케줄링 알고리즘을 수행합니다.
다음 실행할 스레드의 우선순위와 상태를 확인합니다.
이후에는 선택된 스레드를 실행합니다.컨텍스트 전환 완료
새로운 스레드가 실행되면서 문맥 교환이 완료됩니다.
실행 가능한 스레드가 없을 경우, 현재 스레드를 계속 실행합니다.
스레드가 생성될 때 어떤 자원이 사용되는가? 프로세스가 생성될 때 사용되는가? 프로세스가 생성될 때 사용되는 차원과의 차이점은 무엇인가?
프로세스가 생성될 때 사용되는 자원은 다음과 같습니다.
주소 공간
프로세스는 자신의 독립적인 주소 공간을 갖습니다. 즉, 메모리 상에서 실행 중인 다른 프로세스와 서로 격리>되어 있습니다.자원
프로세스는 운영 체제에서 자원을 할당받아 사용합니다. 이 자원에는 CPU 시간, 메모리, 파일 디스크립터, >입출력 장치, IPC(Inter-Process Communication) 등이 포함됩니다.PCB(Process Control Block)
각 프로세스마다 독립적인 PCB가 생성됩니다. PCB에는 프로세스 상태, 메모리 할당 정보, 스케줄링 정보 등>이 저장됩니다.반면에, 스레드가 생성될 때 사용되는 자원은 다음과 같습니다.
스택(Stack)
각 스레드마다 독립적인 스택이 생성됩니다. 스레드가 함수를 호출할 때, 호출된 함수의 지역 변수와 매개 변>수 등이 저장되는 공간입니다.레지스터(Register)
각 스레드마다 독립적인 레지스터 집합이 생성됩니다. 스레드가 실행되는 동안 사용하는 레지스터 값이 저장되>는 공간입니다.TCB(Thread Control Block)
각 스레드마다 독립적인 TCB가 생성됩니다. 스레드의 상태, 우선순위, 스택 포인터 등의 정보가 저장되는 공>간입니다.프로세스는 운영 체제에서 자원을 할당받아 주소 공간을 생성합니다. 즉, 프로세스는 자신의 주소 공간을 갖고 있습니다.
스레드는 프로세스의 자원(주소 공간, 힙 등)을 공유합니다. 스레드는 자신의 스택과 레지스터, TCB 등의 자원을 갖고 있습니다.
다대다 모델을 사용하여 운영체제가 사용자 수준 스레드를 커널에 매핑하고 매핑은 LWP(Light Weight Process)를 사용한다고 가정하자. 또한 개발자는 실시간 시스템에서 사용할 실시간 스레드를 만들 수 있다고 하자. 실시간 스레드를 LWP에 바인딩해야 하는가? 여러분의 답을 설명하라.
LWP(Light Weight Process)란?(p.211)
LWP는 Light Weight Process의 약어로, 가벼운 가상 프로세스를 의미합니다. LWP는 운영 체제에서 사용되는 쓰레드와 비슷한 개념으로, 쓰레드를 구현하는 방법 중 하나입니다.
LWP는 하나의 프로세스에 여러 개 생성될 수 있으며, 각각의 LWP는 독립적인 스택과 레지스터를 갖습니다. 운영 체제에서는 LWP 단위로 스케줄링하며, 각각의 LWP는 여러 개의 쓰레드를 처리할 수 있습니다.
LWP를 사용하면, 쓰레드를 구현하는 데 필요한 추가적인 운영 체제 자원이 최소화됩니다. 이러한 이유로, LWP 기반의 스레드는 경량화되어 있으며, 쓰레드 간 전환이 빠르고 효율적입니다.
LWP는 다양한 운영 체제에서 지원되며, 예를 들어 리눅스에서는 NPTL(Native POSIX Thread Library)에서 LWP를 사용하여 쓰레드를 구현합니다.
실시간 스레드를 LWP에 바인딩해야 할 지 여부는 상황에 따라 다를 수 있습니다. 일반적으로 실시간 시스템에서는 실시간 스레드가 우선적으로 실행되어야 하기 때문에, 실시간 스레드를 LWP에 바인딩하는 것이 좋습니다.
반면에, 실시간 스레드를 LWP에 바인딩하지 않으면, 운영 체제 스케줄러가 스레드를 어떤 LWP에 할당할지 결정합니다. 이 경우, 스레드가 실행되기까지 다른 스레드나 프로세스가 우선 실행될 가능성이 있습니다. 이러한 지연은 실시간 시스템에서는 치명적일 수 있습니다.
따라서, 실시간 시스템에서는 실시간 스레드를 LWP에 바인딩하는 것이 좋습니다. 이렇게 하면 스레드가 우선적으로 실행되고, 지연 시간이 최소화됩니다. 하지만 일부 상황에서는 실시간 스레드가 다른 LWP에서 실행되는 것이 더 효율적일 수도 있으므로, 상황에 따라 결정해야 합니다.