스레드 04. 컨텍스트 스위칭(Context Switching)
4. 컨텍스트 스위칭(Context Switching)
컨텍스트 스위칭은 컴퓨터 시스템에서 CPU가 하나의 작업(프로세스 또는 스레드)을 중지하고, 다른 작업을 수행하기 위해 작업의 상태(Context)를 저장하고 복원하는 과정을 말합니다. 이 과정은 멀티태스킹 환경에서 필수적입니다. 왜냐하면 CPU는 한 번에 하나의 작업만 처리할 수 있기 때문에, 여러 작업(프로세스 또는 스레드)을 빠르게 전환하면서 마치 동시에 처리하는 것처럼 보이게 해야 하기 때문입니다.
4.1 컨텍스트(Context)란?
컨텍스트는 CPU가 현재 처리하고 있는 작업의 상태 정보를 의미합니다. 구체적으로는 다음과 같은 정보를 포함합니다:
- 프로그램 카운터(Program Counter): 현재 실행 중인 명령어의 주소.
- 레지스터(Registers): CPU에서 작업 중인 데이터를 저장하는 공간.
- 스택 포인터(Stack Pointer): 현재 작업의 스택(함수 호출 정보, 로컬 변수 등)을 가리키는 포인터.
- 프로세스/스레드 상태(Process/Thread State): 작업의 현재 상태를 나타내는 정보(예: 실행 중, 대기 중 등).
4.2 컨텍스트 스위칭이 필요한 이유
멀티태스킹을 구현하려면 CPU가 여러 작업을 처리하는 것처럼 보여야 합니다. 하지만 CPU는 한 번에 하나의 명령어만 처리할 수 있기 때문에, 빠르게 작업을 전환하면서 각 작업이 일정 시간을 얻도록 해야 합니다. 이때 CPU가 현재 작업의 상태를 저장하고, 다음 작업의 상태를 불러오는 과정이 컨텍스트 스위칭입니다.
즉, 컨텍스트 스위칭을 통해:
- 멀티태스킹이 가능해집니다. 여러 프로세스와 스레드가 실행 중인 것처럼 보이지만, 실제로는 CPU가 하나의 작업을 빠르게 전환하여 처리하는 것입니다.
- 공정한 CPU 자원 분배가 이루어집니다. CPU는 각 작업에 적절한 시간을 배분하여, 하나의 작업이 너무 오랫동안 CPU를 독점하지 않도록 합니다.
4.3 컨텍스트 스위칭의 동작 과정
- 현재 작업의 상태 저장: CPU가 현재 작업(프로세스 또는 스레드)을 중단하기 전에, 그 작업의 모든 상태(프로그램 카운터, 레지스터 값 등)를 저장합니다. 이 정보는 보통 PCB(Process Control Block) 또는 TCB(Thread Control Block)이라는 메모리 구조에 저장됩니다.
- 다음 작업의 상태 복원: CPU는 대기 중인 다른 작업의 상태를 PCB나 TCB에서 불러와 복원합니다. 이때 CPU는 이전 작업이 어디에서 중단되었는지, 어떤 값을 가지고 있었는지를 알 수 있습니다.
- 새로운 작업 실행: CPU는 복원된 상태에서 다음 작업을 이어서 실행합니다. 이 작업이 끝나거나 일정 시간 동안 실행된 후, 다시 다른 작업으로 전환됩니다.
이 과정이 매우 빠르게 반복되면서 여러 작업이 동시에 실행되는 것처럼 보이게 됩니다.
4.4 컨텍스트 스위칭의 비용
컨텍스트 스위칭에는 오버헤드(Overhead)가 발생합니다. 즉, CPU가 작업을 전환할 때 상태를 저장하고 복원하는 과정은 일정한 시간이 소요되며, 이는 CPU 자원을 소모하게 됩니다. 컨텍스트 스위칭이 빈번하게 일어나면 CPU가 실제 작업을 처리하는 시간보다 스위칭에 소요되는 시간이 많아질 수 있습니다.
4.4.1 컨텍스트 스위칭 비용이 발생하는 이유
- 상태 저장과 복원: 현재 작업의 모든 상태를 저장하고 다음 작업의 상태를 복원하는 데 시간이 소요됩니다.
- 캐시 미스(Cache Miss): 새로운 작업으로 전환할 때, CPU 캐시가 새로운 작업에 맞게 다시 로드되어야 할 수 있습니다. 이는 캐시 미스를 발생시켜 성능 저하를 유발할 수 있습니다.
- TLB 플러시(TLB Flush): 컨텍스트 스위칭 시에 페이지 테이블이 새롭게 설정되어야 하므로, TLB(Translation Lookaside Buffer)라는 캐시 메모리가 무효화될 수 있습니다.
4.4.2 컨텍스트 스위칭을 최소화하는 방법
- 스레드 풀(Thread Pool)을 사용하여 불필요한 스레드 생성을 줄이고, 스레드 간 컨텍스트 스위칭 빈도를 줄일 수 있습니다.
- I/O 바운드 작업의 경우 CPU가 작업을 기다리는 동안 컨텍스트 스위칭을 많이 발생시키므로, 효율적인 비동기 프로그래밍을 통해 이를 줄일 수 있습니다.
4.5 컨텍스트 스위칭과 멀티스레딩
멀티스레딩 환경에서는 여러 스레드가 동시에 실행되는 것처럼 보이지만, 실제로는 CPU가 각 스레드에 할당된 시간을 교대로 배분하는 방식으로 처리됩니다. 이 과정에서 컨텍스트 스위칭이 자주 일어나게 됩니다.
단일 코어 CPU에서는 CPU가 여러 스레드 중 하나의 스레드를 일정 시간 동안 실행하다가, 다른 스레드로 전환합니다. 이는 시분할 방식(Time-sharing)으로 이루어집니다.
멀티코어 CPU에서는 각 코어가 독립적으로 스레드를 실행할 수 있습니다. 하지만 스레드 수가 코어 수보다 많으면 여전히 컨텍스트 스위칭이 발생합니다. 코어 간에도 컨텍스트 스위칭이 필요할 수 있는데, 이때 캐시 메모리 간의 데이터 불일치나 캐시 미스로 인한 성능 저하가 발생할 수 있습니다.
4.6 컨텍스트 스위칭의 예시
- 운영체제의 스케줄러(Scheduler): 운영체제는 각 프로세스나 스레드가 CPU 시간을 공정하게 할당받을 수 있도록 스케줄러를 통해 컨텍스트 스위칭을 관리합니다. 스케줄러는 우선순위(priority), 시간 할당(time slice) 등을 기반으로 어떤 작업을 먼저 실행할지 결정하고, 컨텍스트 스위칭을 수행합니다.
- 멀티스레드 웹 서버: 웹 서버에서 여러 사용자의 요청을 동시에 처리할 때, 서버는 각 요청을 스레드로 처리합니다. 이때 CPU는 여러 요청 스레드 사이에서 컨텍스트 스위칭을 수행하면서 각 요청을 처리합니다.
- 게임 엔진: 게임은 여러 스레드를 사용하여 그래픽 렌더링, 사용자 입력 처리, 물리 연산 등을 동시에 처리해야 합니다. 이 과정에서도 CPU는 각 작업을 처리하기 위해 컨텍스트 스위칭을 자주 수행하게 됩니다.
4.7 컨텍스트 스위칭과 관련된 개념
- 선점형 스케줄링(Preemptive Scheduling): CPU가 강제로 현재 실행 중인 작업을 중단하고 다른 작업으로 전환하는 방식입니다. 대부분의 운영체제가 이 방식을 사용하며, 컨텍스트 스위칭은 이 과정에서 필수적입니다.
- 비선점형 스케줄링(Non-preemptive Scheduling): 한 작업이 완료될 때까지 CPU가 그 작업을 중단하지 않는 방식입니다. 이 경우 컨텍스트 스위칭이 적게 발생하지만, 응답성이 떨어질 수 있습니다.
4.8 컨텍스트 스위칭 최적화
컨텍스트 스위칭의 오버헤드를 줄이기 위해서는 다음과 같은 방법을 사용할 수 있습니다:
- 스레드 풀(Thread Pool) 사용: 새로운 스레드를 계속 생성하는 대신, 일정한 수의 스레드를 미리 만들어서 재사용하면 스위칭 빈도를 줄일 수 있습니다.
- 비동기 프로그래밍: I/O 작업을 기다리는 동안 CPU가 빈번한 컨텍스트 스위칭을 발생시키지 않도록 비동기 방식으로 작업을 처리합니다.
- 락(lock) 사용 최소화: 불필요한 락 사용을 줄여 스레드 간 경쟁을 줄이고, 컨텍스트 스위칭 빈도를 줄일 수 있습니다.