[Operating System] CPU 스케줄링

남태일·2023년 12월 7일

Operating System

목록 보기
5/9
post-thumbnail

저번 글에서는 프로세스의 실행 단위인 스레드에 대해 알아보았다.

스레드 하나 당 CPU 코어 하나를 할당 받아 실행된다.
여러 개의 프로세스가 실행되고 있고 스레드가 많아졌을 때, 운영체제는 프로세스 스케줄링 또는 스레드 스케줄링을 수행한다.

최신 운영체제에서는 실질적으로 프로세스가 아닌 스레드 단위로 스케줄링 한다.
그러나 "프로세스 스케줄링"과 "스레드 스케줄링" 용어는 상호 교환적으로 사용된다.

이번 글에서는 일반적인 스케줄링 개념에 "프로세스 스케줄링" 용어를 사용하고, 스레드에 국한된 개념을 가리키는 경우 "스레드 스케줄링" 용어를 사용한다.

이번 주제인 "CPU 스케줄링"은, 운영체제가 프로세스 들에게 효율적으로 CPU를 할당하는 것을 말한다.

CPU 스케줄링 개념과 여러 스케줄링 알고리즘을 알아보자.


CPU 스케줄링

운영체제는 프로세스 스케줄링을 하면서 CPU 스케줄링도 수행한다.

어떤 프로세스가 I/O 작업으로 인해 대기해야 하는 경우, 운영체제는 CPU를 그 프로세스로부터 회수해 다른 프로세스에게 할당한다.

이러한 패턴이 계속되면서 CPU를 놀지 않게 한다.

CPU - I/O 버스트 사이클

프로세스 실행은 CPU 실행과 I/O 대기의 사이클로 구성된다.
프로세스들은 이 두 상태 사이를 교대로 왔다 갔다 한다.

프로세스 실행은 CPU 버스트로 시작되며, 뒤이어 I/O 버스트가 발생하고, 그 뒤에 또 CPU 버스트가 번갈아가면서 발생한다.

I/O 중심의 프로세스는 짧은 CPU 버스트가 많이 있으며, CPU 중심의 프로세스는 긴 CPU 버스트를 가질 수 있다.
이러한 분포는 CPU 스케줄링 알고리즘을 구현할 때 매우 중요하다.
아래 그림은 프로세스들의 일반적인 CPU 버스트 빈도를 나타낸다.

CPU 스케줄러

CPU가 유휴 상태가 될 때마다 운영체제는 준비 큐에 있는 프로세스 중에서 하나를 선택하여 CPU를 할당한다.
준비 큐에 있는 레코드들은 일반적으로 PCB이다.
프로세스 선택은 CPU 스케줄러에 의해 수행된다.

선점(Preemptive) 및 비선점(Nonpreemptive) 스케줄링

CPU 스케줄링 결정은 다음의 네 가지 상황에서 발생할 수 있다.

  1. 프로세스가 I/O 요청이나, 자식 프로세스가 종료되기를 기다리기 위해 wait()을 호출하여 실행 상태에서 대기 상태로 전환될 때
  2. 프로세스가 인터럽트와 같은 이유로 실행 상태에서 준비 상태로 전환될 때
  3. 프로세스가 입출력 완료와 같은 이유로 대기 상태에서 준비 상태로 전환될 때
  4. 프로세스가 종료될 때

1번과 4번 상황에서의 스케줄링은 비선점이다.
다른 상황은 선점이다.

비선점(Nonpreemptive)

CPU가 프로세스에 할당되면, 프로세스가 종료되거나 대기 상태로 전환해 CPU를 반납할 때까지 계속 점유한다.

선점(Preemptive)

CPU가 프로세스에 할당되면, CPU 할당 시간이 만료될 때까지만 CPU를 할당 받고, 시간이 만료되면 운영체제가 CPU를 다시 가져간다.
현대의 거의 모든 최신 운영체제들은 선점 스케줄링 알고리즘을 사용한다.

디스패처(Dispatcher)

디스패처는 CPU 코어의 제어권을 CPU 스케줄러가 선택한 프로세스에 주는 모듈이다.
디스패처는 다음과 같은 역할을 수행한다.

  • 문맥 교환
  • 사용자 모드로 전환
  • 프로그램을 다시 시작하기 위해 사용자 프로그램의 적절한 위치로 이동

디스패처는 모든 프로세스의 문맥 교환시 호출되므로 최대한 빨리 수행되어야 한다.
디스패처가 하나의 프로세스를 정지하고 다른 프로세스의 실행하는데까지 소요되는 시간을 "디스패치 지연(Latency)" 라고 한다.


스케줄링 기준

CPU 스케줄링 알고리즘은 여러 가지가 있으며 각각의 특성이 존재한다.
CPU 스케줄링 알고리즘 비교를 위한 여러 기준이 있으며, 각 특성에 따라 최선의 알고리즘을 결정하는데 큰 차이가 발생한다.

사용되는 스케줄링 기준은 아래와 같다.

  • CPU 이용률(CPU Utilization)
    • CPU를 얼마나 사용하고 있는지를 나타낸다.
  • 처리량(Throughtput)
    • 단위 시간당 완료된 프로세스의 개수이다.
  • 총 처리 시간(Turnaround Time)
    • 특정 프로세스가 실행된 시점부터 완료된 시간까지의 간격이다.
    • 준비 큐에서 대기한 시간, CPU 실행 시간, I/O 시간을 합한 시간이다.
  • 대기 시간(Waiting Time)
    • 준비 큐에서 대기한 시간이다.
    • CPU 스케줄링 알고리즘은 프로세스 실행 또는 I/O 수행 시간의 양에 영향을 미치지 않는다.
    • 스케줄링 알고리즘은 단지 프로세스가 준비 큐에서 대기하는 시간의 양에만 영향을 준다.
  • 응답 시간(Response Time)
    • 프로세스에게 요청을 보내고 응답이 시작되는데 까지 걸리는 시간이다.

가장 이상적인건 CPU 이용률과 처리량을 최대화하고, 나머지를 최소화 하는 것이다.


스케줄링 알고리즘

CPU 스케줄링은 준비 큐에 있는 어느 프로세스에게 CPU 코어를 할당할 것인지를 결정한다.

스케줄링 알고리즘을 설명할 때에는, CPU 코어 1개를 사용한다고 가정한다.

여러 가지의 CPU 스케줄링 알고리즘을 알아보자.

선입 선처리 스케줄링(FCFS)

CPU를 먼저 요청한 프로세스가 CPU를 할당 받는 방식이다.
비선점 방식이다.
큐로 쉽게 관리할 수 있다.
시간이 긴 프로세스가 먼저 실행되면, 대기 하는 프로세스들의 대기 시간이 늘어나는 단점이 있다.
이를 호위 효과(Convoy Effect)라고 한다.

최단 작업 우선 스케줄링(SJF)

CPU 버스트 길이가 가장 짧은 프로세스부터 CPU를 할당한다.
동일한 CPU 버스트 길이를 가질 경우 FCFS를 적용한다.

SJF 알고리즘이 최적이긴 하지만, 다음 CPU 버스트의 길이를 알 방법이 없어서 구현할 수 없다.
대신 다음 CPU 버스트 길이를 예측하여 근사하게 구현할 수는 있다.

라운드 로빈 스케줄링(RR)

FCFS 스케줄링과 유사하지만, 선점이 추가된다.
시간 할당량(Time Quantum) 또는 타임 슬라이스(Time Slice)라고 하는 작은 단위의 시간을 정의한다.
일반적으로 10~100ms 이다.

CPU 스케줄러는 준비 큐를 돌면서 프로세스당 타임 슬라이스 동안 CPU를 할당한다.

프로세스의 CPU 버스트 시간이 타임 슬라이스보다 작은 경우 CPU를 자발적으로 반납한다.
그 외에는 타임 슬라이스가 지나면, 운영체제에게 인터럽트를 발생시켜 선점되고 준비 큐로 돌아간다.

RR 방식은 타임 슬라이스의 크기에 영향을 많이 받는다.
타임 슬라이스가 너무 길면 FCFS와 동일한 방식이 되고, 너무 짧으면 문맥 교환이 빈번하게 일어난다.

우선 순위 스케줄링(Priority)

프로세스에 우선 순위를 부여하여 높은 우선 순위를 가지는 프로세스부터 CPU를 할당하는 방식이다.

새로 도착한 프로세스의 우선 순위와 현재 실행되는 프로세스의 우선 순위를 비교하여 선점, 비선점을 선택하여 구현할 수 있다.

우선 순위 스케줄링의 문제점은 "기아 상태(Starvation)"이 발생할 수 있다는 점이다.
기아 상태는 낮은 우선 순위의 프로세스들이 무한정 기다리는 상태를 말한다.

기아 상태를 해결하기 위해 에이징(Aging) 기법을 사용한다.
에이징 기법은 대기하는 프로세스들의 우선 순위를 점차 높이는 방식이다.

다단계 큐 스케줄링

우선 순위마다 준비 큐를 여러 개 사용하는 스케줄링 방식이다.
우선 순위가 가장 높은 큐에 있는 프로세스부터 CPU를 할당한다.
우선 순위가 낮은 프로세스는 기아 현상이 발생할 수 있다.

프로세스 유형에 따라 다른 우선 순위를 가지는 개별 큐로 분할될 수도 있다.
흔히 "포어그라운드" 프로세스와 "백그라운드" 프로세스를 구분한다.

다단계 피드백 큐 스케줄링

프로세스가 큐 간의 이동이 가능한 스케줄링 방식이다.

프로세스들을 CPU 버스트 성격에 따라 구분한다.
어떤 프로세스가 CPU 시간을 너무 많이 사용하면 낮은 우선 순위 큐로 이동시킨다.
CPU 버스트 시간이 짧은 I/O Bound 프로세스와 대화형(Interactive) 프로세스를 높은 우선 순위 큐로 이동시킨다.

또한 낮은 우선 순위의 큐에서 너무 오래 대기하는 프로세스는 에이징 기법을 적용하여 높은 우선 순위 큐로 이동할 수 있으며, 기아 상태를 예방한다.

다단계 피드백 큐 스케줄러의 정의에 의하면, 이 스케줄링 알고리즘은 가장 일반적인 CPU 스케줄링 알고리즘이다.


스레드 스케줄링

스레드는 "사용자 수준" 스레드와 "커널 수준" 스레드로 나뉜다.
사용자 수준 스레드는 스레드 라이브러리에 의해 관리되고 커널은 이 존재를 알지 못한다.
커널 수준 스레드는 커널에서 사용되는 스레드이며 운영체제에 의해 스케줄링된다.

대부분 최신 운영체제에서는 스케줄 대상이 커널 스레드이다.
사용자 수준 스레드가 CPU를 할당받아 실행되기 위해서는 커널 수준 스레드와 매핑되어야 한다.
현대 운영체제에서는 대부분 사용자 스레드 하나 당 커널 스레드 하나가 매핑된다.
이를 일대일 모델이라고 한다.

경쟁 범위(Contention Scope)

프로세스 경쟁 범위

사용자 스레드는 스레드 라이브러리에 의해 스케줄링 되며, 동일한 프로세스에 속한 스레드 사이에서 CPU 경쟁을 한다.
이러한 경쟁 범위를 "프로세스 경쟁 범위"라고 한다.

시스템 경쟁 범위

사용자 스레드가 실제로 CPU를 할당 받아 실행이 되려면, 커널 스레드와 매핑이 되어야한다.
그 후, 운영체제에 의해 커널 스레드가 CPU를 할당 받고 해당 스레드에 매핑된 사용자 스레드가 실행된다.
이때, 어떤 커널 스레드에게 CPU를 할당할 것인지 결정하기 위해 커널은 "시스템 경쟁 범위"를 사용한다.


멀티 코어 스케줄링

지금까지는 싱글 코어 CPU 스케줄링을 설명했다.

현대에는 대부분 멀티 코어 CPU를 사용한다.
멀티 코어 CPU를 사용하면, 여러 스레드가 병렬 실행이 될 수 있다.
하지만 그만큼 스케줄링이 복잡해진다.

멀티 스레드 처리 코어

연구자들은 프로세서가 메모리에 접근할 때 데이터가 사용 가능할 때까지 많은 시간을 허비한다는 것을 발견하였다.
이를 "메모리 스톨" 이라고 한다.

메모리 스톨은 CPU가 메모리보다 훨씬 빠른 속도로 작동하기 때문에 발생한다.
아래 그림 예시에서는 CPU가 메모리의 데이터를 기다리느라 최대 50% 시간을 허비할 수 있는 것을 나타낸다.

메모리 스톨을 해결하기 위해, 최근의 많은 CPU는 "멀티 스레드 처리 코어"를 하드웨어적으로 구현하였다.
멀티 스레드 처리 코어는 하나의 코어에 2개 이상의 "하드웨어 스레드"가 할당된다.
이렇게 하면 하나의 하드웨어 스레드가 메모리를 기다리는 동안, 다른 하드웨어 스레드로 전환할 수 있다.

운영체제 입장에서, 각 하드웨어 스레드는 소프트웨어 스레드를 실행할 수 있는 논리적 CPU로 인식한다.
이를 칩 멀티 스레딩 이라고 부른다.

Intel CPU는, 싱글 코어에 여러 하드웨어 스레드를 할당 하는 것을 "하이퍼 스레딩" 이라고 부른다.

물리적 코어(캐시 및 파이프라인)의 자원은 하드웨어 스레드 간에 공유되어야 하기 때문에, 코어는 한 번에 하나의 하드웨어 스레드만 실행할 수 있다.

따라서, 소프트웨어 스레드에 하드웨어 스레드를 할당하는 스케줄링과
하드웨어 스레드에 코어를 할당하는 스케줄링 두 단계가 필요하다.

이전까지 논의했던 CPU 스케줄링이 단계 1 스케줄링이다.
단계 2 스케줄링은 코어 내부적으로 처리한다.

부하 분산(Load Balancing)

멀티 코어를 최대한 활용하려면, 부하를 모든 코어에 균등하게 배분하는 것이 중요하다.
이를 부하 분산이라고 한다.

부하 분산은 각 코어가 "실행할 스레드들을 대기 시킬 자신 만의 준비 큐"를 가지는 경우에만 필요한 기능이다.
모든 코어가 공통의 큐를 가지고 있는 시스템에서는 부하 분산이 필요하지 않다.

push 이주

특정 작업이 주기적으로 각 코어의 부하를 검사하고, 만일 불균형 상태라면 과부하인 코어에서 쉬거나 다른 코어로 스레드를 이동(push) 시킨다.

pull 이주

쉬고 있는 코어가 현재 바쁜 코어를 기다리는 스레드를 자신에게 이동(pull) 시킨다.

두 이주 방식은 병렬적으로 구현된다.


실시간 CPU 스케줄링

실시간으로 CPU를 스케줄링 할 때는 특별한 쟁점을 고려해야 한다.

일반적으로 soft 실시간 시스템과 hard 실시간 시스템으로 구분한다.

soft 실시간 시스템은 중요한 실시간 프로세스가 스케줄 되는 시점에 관해 아무런 보장을 하지 않는다.

hard 실시간 시스템은 프로세스가 반드시 마감시간까지 서비스를 받아야 하며, 마감시간이 지난 이후에 서비스를 받는 것은 못 받는 것과 동일한 결과를 낳는다.

soft, hard 실시간 운영체제에서 프로세스 스케줄링과 관련된 고려사항들을 알아보자.

지연시간 최소화

실시간 운영체제는 일반적으로 실시간으로 발생하는 이벤트를 기다린다.
이벤트가 발생하면, 시스템은 가능한 빨리 그에 응답하고 그에 맞는 동작을 수행해야 한다.

이벤트 지연시간은 이벤트가 발생해서 그에 맞는 서비스가 수행될 때까지의 시간을 말한다.

다음의 두 가지 지연시간이 실시간 시스템의 성능을 좌우한다.

  1. 인터럽트 지연시간
  2. 디스패치 지연시간

인터럽트 지연시간

CPU에 인터럽트가 발생한 시점부터 해당 인터럽트 처리 루틴이 시작하기 까지의 시간을 말한다.

인터럽트가 발생하면 운영체제는 현재 수행 중인 명령어를 완수하고, 발생한 인터럽트의 종류를 결정한다.
그리고 현재 실행 중인 프로세스의 상태를 저장해 놓는다.
이러한 작업을 모두 수행하는 데 걸리는 시간이 인터럽트 지연시간이다.

디스패치 지연시간

스케줄링 디스패처가 하나의 프로세스를 멈추고 다른 프로세스를 시작하기까지 걸린 시간을 말한다.

디스패치 지연의 충돌 단계는 두 가지 요소로 구성되어 있다.

  • 커널에서 동작하는 프로세스에 대한 선점
  • 높은 우선순위의 프로세스가 필요한 자원을 낮은 우선순위 프로세스에서 반납.

우선순위 기반 스케줄링

실시간 운영체제에서 가장 중요한 기능은 실시간 프로세스에 CPU가 필요할 때 바로 응답을 해주는 것이다.
따라서 실시간 운영체제의 스케줄러는 선점을 이용한 우선순위 기반의 알고리즘을 지원해야만 한다.

Linux, Windows, Solaris 운영체제들은 실시간 프로세스에게 가장 높은 스케줄링 우선권을 부여한다.

그러나 선점 및 우선순위 기반의 스케줄러를 제공하는 것은 soft 실시간 기능을 제공하는 것에 불과하다.

hard 실시간 시스템에서는 실시간 작업이 마감시간(deadline) 내에 확실히 수행되는 것을 보장해야만 하며, 부가적인 스케줄링 기법이 필요하다.

각각의 프로세스들은 주기적으로 CPU가 필요하며, 아래와 같은 특성을 가진다.

  • 고정된 수행 시간 t
  • CPU로부터 반드시 서비스를 받아야 하는 마감시간 d
  • 주기 p

수행시간, 마감시간, 주기의 관계는 0 <= t <= d <= p 이다.

스케줄러는 프로세스의 이 특성을 이용하여 우선순위를 정한다.

Rate-Monotonic 스케줄링

선점 가능한 우선순위 정책을 이용하여 주기 태스크들을 스케줄 한다.
낮은 우선순위 프로세스가 실행 중이고, 높은 우선순위 프로세스가 실행 준비가 되면 높은 우선순위 프로세스가 낮은 우선순위 프로세스를 선점한다.

주기가 짧은 프로세스가 높은 우선 순위를 가지게된다.
이 정책은 CPU를 더 자주 이용하는 프로세스에게 높은 우선순위를 부여한다.
또한, Rate-Monotonic 스케줄링은 주기 프로세스들의 처리 시간이 각각의 CPU 버스트와 같다고 가정한다.

Earliest Deadline First 스케줄링

마감시간에 따라서 우선순위를 동적으로 부여한다.
마감시간이 빠를수록 우선순위가 높아진다.

EDF에서는, 프로세스가 실행 가능하게 되면 자신의 마감시간을 시스템에 알려야 한다.

EDF 스케줄링 알고리즘은 프로세스들이 주기적일 필요도 없고, CPU 할당 시간도 상수 값으로 정해질 필요가 없다.
대신, 프로세스가 실행 가능해질 때 마감시간을 스케줄러에게 알려주어야 한다.

EDF는 이론적으로 최적이다.
모든 프로세스가 마감시간을 만족시키도록 스케줄 할 수 있고, CPU 이용률도 100%가 될 수 있다.

그러나 실제로는 문맥 교환 비용 때문에 100%의 CPU 이용률은 불가능하다.


실제 운영체제의 스케줄링 기법

Linux, Windows 운영체제의 스케줄링 정책을 알아보자.

"프로세스 스케줄링" 이라는 용어는 일반적인 의미로 사용한다.
실제로 Windows 시스템의 경우에는 "커널 스레드" 스케줄링에 관해 설명하고, Linux 시스템은 "태스크" 스케줄링에 관해 설명한다.

참고로, Linux에서 태스크는 프로세스 또는 스레드들을 통틀어서 말한다.

Linux 스케줄링

2.6.23 버전의 커널부터는 완전 공평 스케줄러(CFS)를 Linux 시스템의 기본 스케줄링 알고리즘으로 사용한다.

Linux 스케줄러는 각 클래스별로 특정 우선순위를 부여받는 "스케줄링 클래스" 기반으로 동작한다.
스케줄러는 다음에 실행될 태스크로 높은 우선순위 클래스에 속한 가장 높은 우선순위의 태스크를 선택한다.

표준 Linux 커널은 "기본 스케줄링 클래스"와 "실시간 스케줄링 클래스"의 두 클래스를 구현한다.

CFS 스케줄러는 각 태스크에 CPU 처리시간의 비율을 할당한다.
이 비율은 각 태스크에 할당된 "nice" 값에 기반을 두고 계산된다.
nice 값은 -20 부터 19까지의 범위를 가지며, 값이 적을수록 우선순위가 높다.

CFS는 모든 태스크가 적어도 한 번씩은 실행할 수 있는 시간인 "목적 지연시간"을 찾는다.
CPU 시간의 비율은 목적 지연시간의 값으로부터 할당된다.

CFS는 태스크마다 vruntime이라는 변수에 태스크가 실행된 시간을 기록하여 "가상 실행 시간"을 저장한다.
vruntime 값은 태스크의 우선순위에 따라 달라지는데, 높은 우선순위의 태스크는 vruntime 값이 작고, 낮은 우선순위의 태스크는 vruntime 값니 낮다.
스케줄러는 다음 실행될 태스크로 단순히 가장 작은 vruntime을 가지는 태스크를 선택한다.

같은 nice 값을 가지는 두 태스크가 있다고 가정해보자.
한 태스크는 I/O Bound이고, 한 태스크는 CPU Bound라고 해보자.
I/O Bound 태스크는 CPU를 짧게 사용할 것이고, CPU Bound 태스크는 CPU를 길게 사용할 것이다.
따라서, I/O Bound 태스크의 vruntime 값은 CPU Bound 태스크보다 작아지게 되어 우선순위가 높아지게 된다.

Linux는 또한 실시간 정책을 사용하는 태스크에게 보통의 태스크보다 높은 우선순위를 주고 실행한다.
실시간 태스크와 보통의 태스크의 우선순위 영역을 따로 분리해서 관리한다.

보통의 태스크들은 nice 값에 기반을 둔 우선순위가 할당되며, -20이 우선순위 100에 해당하고, 19가 우선순위 139에 해당된다.

CFS 스케줄러는 스레드 이주를 최소화하는 정교한 기술을 사용하여 부하 분산을 지원한다.

Windows 스케줄링

Windows는 우선순위 기반의 선점 스케줄링 알고리즘을 사용한다.
Windows는 가장 높은 우선순위의 스레드가 항상 실행되도록 보장한다.

Windows 커널 중 스케줄링을 담당하는 부분을 "디스패처"라고 부른다.
디스패처에 의해 선택된 스레드는, 더 높은 우선순위 스레드에 의해 선점되거나, 연산이 다 끝나거나, 시간 할당량이 만료되거나, 입출력 작업을 위해 멈출때까지 실행된다.

스레드가 실행 중에 우선순위가 더 높은 실시간 스레드가 준비 상태가 되면, 우선순위가 낮은 스레드는 선점된다.
이로인해 실시간 스레드가 CPU를 할당받을 수 있는 우선권을 준다.

디스패처는 스레드 실행 순서를 정하기 위해 32단계의 우선순위를 사용한다.
우선순위는 두 개의 클래스로 구분된다.
"가변 클래스"에 속한 스레드의 우선순위는 1~15까지이다.
"실시간 클래스"에 속한 스레드의 우선순위는 16~31까지이다.
우선순위가 0인 스레드는 메모리 관리를 위해 사용된다.

디스패처는 각 우선순위를 위한 큐를 사용하고, 이 큐를 높은 우선순위부터 조사하면서 준비 상태의 스레드가 있는지를 본다.
만약, 스레드가 없으면 idle 스레드라는 특수한 스레드를 실행시킨다.

1~31의 우선순위 값은 스레드가 속한 우선순위 클래스와 그 클래스 내부의 상대적인 우선순위에 기반을 둔다.

스레드의 시간 할당량이 만료되면, 스레드는 인터럽트 된다.
인터럽트된 스레드가 가변 우선순위 클래스에 속한다면, 우선순위가 낮아지는데 기본 우선순위보다 낮아지지는 않는다.
스레드의 우선순위를 이렇게 낮춰서 CPU Bound 스레드가 CPU를 독점하는 것을 방지한다.

가변 우선순위 스레드가 대기 상태에서 풀려나면, 디스패처는 우선순위를 높여준다.
만약 키보드 입출력을 기다렸다면 우선순위를 많이 높여주고, 디스크를 기다렸다면 보통 정도로 높여준다.

이러한 우선순위 관리를 통해, CPU Bound 스레드는 후위로 실행되면서 남는 CPU 사이클을 활용한다.
또한, I/O Bound 스레드는 I/O 작업을 많이 하도록 한다.
이 전략은 UNIX와 같은 운영체제에서도 많이 사용되며, 마우스와 윈도우를 쓰는 대화형 스레드에 빠른 응답 시간을 허용한다.

사용자가 대화형 프로그램을 실행 중일 때는 그 프로세스가 특별히 좋은 성능을 얻도록 해야한다.
이러한 이유로 Windows는 NORMAL_PRIORITY_CLASS에 있는 프로세스에 특별한 스케줄링 법칙을 적용한다.
Windows는 현재 화면에서 선택된 포어그라운드 프로세스와, 선택되지 않은 백그라운드 프로세스를 구분한다.
Windows는 포어그라운드 프로세스에게 시간 할당량을 보통 3배 정도 더 증가시켜 성능을 올린다.

Windows는 또한 해당 스레드가 가장 적합한 CPU 코어에 스케줄 되도록 시도한다.
Windows는 논리 프로세서 집합(SMT)를 생성한다.
하이퍼스레드 SMT 시스템에서는 동일한 CPU 코어에 속하는 하드웨어 스레드가 동일한 SMT 집합에 속한다.
논리 프로세서는 0번부터 번호가 매겨진다.
이중 스레드/쿼드코어 CPU에는 4개의 SMT 집합이 만들어진다.

  • {0, 1}, {2, 3}, {4, 5}, {6, 7}

스케줄러는 캐시 메모리 접근 불이익을 피하고자, 스레드를 동일한 SMT 집합에서 실행되게끔 시도한다.

여러 CPU 코어에 부하 분산을 하기 위해, 각 스레드에는 스레드가 선호하는 CPU를 나타내는 숫자가 배정된다.
초기 시드 값을 통해 배정되며, 이 시드는 프로세스가 새로운 스레드를 생성할 때마다 증가하여 부하를 다른 CPU 코어에(SMT에) 분배한다.
모든 프로세스의 첫 번째 스레드에 처리기 0이 배정되는 것을 피하고자, 프로세스마다 다른 시드 값이 할당되어 적절한 부하 분산을 수행한다.

0개의 댓글