Lottery Scheduling¶
스케줄링 : 비례 배분¶
비례 배분(Proportional Share) 스케줄러, 혹은 공정 배분(fair share) 이라고도 하는 유형의 스케줄러
핵심 질문 : 어떻게 CPU를 정해진 비율로 배분할 수 있는가
- 특정 비율로 CPU를 배분하는 스케줄러를 어떻게 설계할 수 있는가?
- 그렇게 하기 위한 중요한 기법은 무엇인가?
- 그 기법은 얼마나 효과적인가?
- 비례 배분
반환 시간이나 응답 시간을 최적화하는 대신 스케줄러가 각 작업에게 CPU의 일정 비율을 보장
추첨 스케줄링(lottery scheduling)
다음 실행될 프로세스를 추첨을 통해 결정한다.
더 자주 수행되어야 하는 프로세스는 당첨 기회를 더 많이 준다.
1. 기본 개념 : 추첨권과 무작위성¶
팁 : 무작위성의 이용
추첨권 스케줄링의 큰 장점 중 하나는 무작위성이다.
무작위 방식은 전통적인 결정 방식에 비해 세 가지 장점이 있다.
1. 무작위 방식은 더 전통적인 방식이 잘 해결하지 못하는 특이 상황을 잘 대응한다.
LRU 교체 정책을 생각해 보자 (가상 메모리의 나중 장에서 더 자세히 검토).
LRU는 좋은 교체 알고리즘이지만 반복되는 순차적인 접근 패턴을 보이는 오버헤드에 대해서는 최악의 성능을 보인다.
반면, 무작위 방식에서는 그러한 최악의 경우가 발생하지 않는다.
2. 무작위 추첨 방식은 매우 가볍다.
관리해야 할 상태 정보가 거의 없기 때문이다.
전통적인 공정 배분 스케줄링 알고리즘에서는 각 프로세스가 사용한 CPU 양을 기록해야 한다.
이 정보는 각 프로세스를 실행시킬 때마다 갱신된다.
무작위 추첨 방식에서는 프로세스의 상태 정보만 필요하다 (예, 각 프로세스가 가진 추첨권의 개수).
3. 무작위 추첨 방식은 매우 빠르다.
난수 발생 시간이 빠르기만 하면 결정 역시 빠르게 되고 따라서 속도가 요구되는 많은 경우에 사용될 수 있다.
물론, 속도를 증가시키기 위해서 추첨 과정을 덜 무작위 (pseudo-random)하게 만들기도 한다.
-
Tickets (추첨권, 티켓)
추첨권은 프로세스가 (또는 사용자 또는 그 무엇이든) 받아야 할 자원의 몫을 나타내는 데 사용된다.
프로세스가 소유한 티켓의 개수와 전체 티켓에 대한 비율이 자신의 몫을 나타낸다. -
예시
추첨권은 0 에서 99의 숫자다.
A와 B 두 프로세스가 있다고 가정하자.
A는 75장의 추첨권 (티켓 0 ~ 74) → 75%의 CPU 할당
B 는 25장의 추첨권 (티켓 75 ~99) → 남은 25% CPU 할당
스케줄러는 추첨권을 선택하고 뽑힌 추첨권 값에 따라 실행할 프로세스가 결정된다.
무작위성은 원하는 비율을 정확히 보장하지는 않는다.
하지만, 두 작업이 장시간 실행될수록, 원하는 비율을 달성할 가능성이 높아진다.
2. 추첨 기법¶
팁 : 몫을 표현하기 위한 추첨권의 사용
추첨 (그리고 보폭 (stride)) 스케줄링의 설계에서 가장 기본적인 개념은 추첨권이다.
이 예에서는 추첨권이 CPU를 사용할 수 있는 프로세스의 몫을 나타내는 데 사용되고 있지만 훨씬 더 널리 적용될 수 있다.
예를 들어, 하이퍼바이저의 가상 메모리 관리에 관한 최근의 연구에서 Waldspurger는 게스트 운영체제의 메모리 할당 지분을 나타내는 데 추첨권이 어떻게 사용될 수 있는지 보여 준다.
추첨권을 통해서 현재 소유 지분을 표현할 수 있다.
-
추첨권 화폐 (ticket currency)
이 개념은 사용자가 추첨권을 자신의 화폐 가치로 추첨권을 자유롭게 할당할 수 있도록 허용한다.
시스템은 자동적으로 화폐 가치를 correct global value로 변환한다. -
예시
사용자 A, B가 각각 100장의 추첨권을 받았다고 가정하자. (Global currency = 200)
사용자 A
A1과 A2의 두 개의 작업을 실행 중
사용자 기준 전체 화폐 = 1000장의 추첨권 → 각각 500장의 추첨권을 할당
→ 시스템은 A1과 A2의 몫을 A의 기준 화폐 500장에서 전역 기준 화폐 각각 50장으로 변환한다.
사용자 B
B1 하나의 작업을 실행 중
사용자 B 기준 전체 화폐 = 10장 추첨권 → 프로세스 B1에 10장을 할당.
→ 시스템은 B1의 기준 화폐 10장에서 전역 기준 화폐 100장으로 변환된다.
따라서 전역 추첨권 화폐량 (총 200장) 기준으로 추첨한다.
- 추첨권 양도(ticket transfer)
양도를 통하여 프로세스는 일시적으로 추첨권을 다른 프로세스에게 넘겨줄 수 있다.
이 기능은 클라이언트/서버 환경에서 특히 유용하다.
클라이언트 프로세스는 서버에게 메시지를 보내 자신을 대신해 특정 작업을 해달라고 요청한다.
작업이 빨리 완료될 수 있도록 클라이언트는 서버에게 추첨권을 전달하고 서버가 자신의 요청을 수행하는 동안 서버의 성능을 극대화하려고 한다.
요청을 완수하면 서버는 추첨권을 다시 클라이언트에게 되돌려 주고 먼저와 같은 상황이 된다.
- 추첨권 팽창(ticket inlation)
이 기법에서 프로세스는 일시적으로 자신이 소유한 추첨권의 수를 늘이거나 줄일 수 있다.
화폐 팽창 기법은 프로세스들이 서로 신뢰할 때 유용하다.
서로 신뢰하지 않는 프로세스들이 상호 경쟁하는 환경에서는 좋지 못한 기법이다. (하나의 욕심 많은 프로세스가 매우 많은 양의 추첨권을 자신에게 할당하고 컴퓨터를 장악할 수 있다.)
따라서 어떤 프로세스가 더 많은 CPU 시간을 필요로 한다면 시스템에게 이를 알리는 방법으로 다른 프로세스들과 통신하지 않고 혼자 추첨권의 가치를 상향 조정한다.
3. 구현¶
스케줄링의 가장 큰 장점은 구현이 단순하다는 점이다.
필요한 것은 난수 발생기와 프로세스들의 집합을 표현하는 자료 구조 (예, 리스트), 추첨권의 전체 개수 뿐이다.
리스트를 사용하여 프로세스를 관리한다고 가정하자.
A, B, C 세 개의 프로세스로 구성되고 각자 몇 장의 추첨권을 가진다.
- 추첨 스케줄링 결정 코드

C// counter: 당첨자를 발견했는지 추적하는데 사용됨 int counter = 0; // winner: 0부터 총 추첨권 수 사이의 임의의 값을 얻기 위해 난수 발생기를 호출함 int winner = getrandom(0, totaltickets); // current: 작업 목록을 탐색하는 데 사용 node_t *current = head; // 티켓 값 > winner 를 만족할 때까지 반복 while (current) { counter = counter + current −> tickets; if (counter > winner) break; // 당첨자 발견 current = current−>next; } // "current" 는 당첨자를 가리킴: 당첨자가 실행될 수 있도록 준비
스케줄을 결정하기 위해 먼저 총 추첨권의 개수 \((400)^2\) 중에서 한 숫자를 선택해야 한다.
300이 선택되었다고 하자.
리스트를 순회하며 카운터 값을 이용하여 당첨자를 찾아낸다 .
프로세스 리스트를 순회하면서 counter의 값이 winner의 값을 초과할 때까지 각 추첨권 개수를 counter에 더한다.
값이 초과하게 되면 리스트의 현재 원소가 당첨자가 된다.
당첨 번호가 300인 우리의 예에서는 다음과 같이 진행된다. 먼저 A의 추첨권 개수가 더해져서 counter 값이 100으로 증가한다. 100은 300보다 작기 때문에 계속 루프를 실행한다.
다음 counter는 150(B의 추첨권 개수)으로 갱신되고, 아직 300보다 작기 때문에 다시 순회를 계속한다. 마침내 counter는 400(확실히 300보다 큼)으로 갱신되고 루프를 빠져 나오게 되고 current는 프로세스 C(당첨자)를 가리키게 된다.
일반적으로 리스트를 내림차순으로 정렬하면 이 과정이 가장 효율적이 된다. 정렬 순서는 알고리즘의 정확성에 영향을 주지는 않는다.
그러나 리스트를 정렬해 놓으면 검색 횟수가 최소화되는 것을 보장한다.
특히, 적은 수의 프로세스가 대부분의 추첨권을 소유하고 있는 경우에 효과적이다.
4. 추첨 스케줄링 문제점¶
문제점 1 : 작업 길이가 짧은 경우¶
-
\(U\) : 불공정 지표(unfairness metric)
추첨 스케줄링의 무작위성 때문에 한 작업이 다른 작업보다 먼저 종료될 수 있는데, 이를 정량화한 지표
첫 번째 작업이 종료된 시간 / 두 번째 작업이 종료된 시간으로 나눈 값 -
예시
추첨 스케줄링 동작을 쉽게 이해하기 위해서, CPU를 공유하는 두 개의 작업의 수행 시간을 살펴보자.
각 프로세스는 같은 개수의 추첨권 (100)을 가지고 있으며 실행시간 R = 10 만큼 동일한 실행 시간을 갖는다.
첫 번째 작업은 시간 10에 종료 → 두 번째 작업은 20에서 종료
U = \(10/20\) = 0.5.
두 작업이 거의 동시에 종료하면 U 는 1에 근접해진다. (가장 이상적)
추첨권 배분 방식의 공정성 분석 그림은 평균적인 불공정 정도를 보이고 있다.
두 작업의 수행 시간은 1에서 1000까지 변경시켰으며 30번씩 실행시켰다.
결과는 이 장의 마지막에 제공되는 시뮬레이터를 통하여 생성되었다.
그래프에서 보듯 작업 길이가 길지 않은 경우, 평균 불공정 정도는 심각하다.
작업이 충분한 기간 동안 실행되어야 추첨 스케줄러는 원하는 결과에 가까워진다.
무작위성을 이용하면 스케줄러를 단순하게 (그러나 어느정도 정확하게) 만들 수 있지만, 정확한 비율을 보장할 수 없다.
짧은 기간만 실행되는 경우는 더 그렇다.
문제점 2: 추첨권 배분 방식¶
프로세스들에게 추첨권을 몇 개씩 분배해야 할지에 대해서 미해결 상태이다.
시스템 동작이 추첨권 할당 방식에 따라 크게 달라지기 때문에 상당히 어려운 문제이다.
주어진 작업 집합에 대한 “추첨권 할당 문제”는 여전히 미해결 상태다.
궁여지책으로 사용자가 가장 잘 알고 있다고 가정하고, 각 사용자에게 추첨권을 나누어 준 후 사용자가 알아서 실행시키고자 하는 작업들에게 추첨권을 배분할 수 있지만 완벽한 해결 방법이 아니다.
5. 결정론적 (Deterministic) 방법: 보폭 개념 사용¶
보폭 스케줄링(stride scheduling)¶
- 결정론적 공정 배분 스케줄러
보폭 스케줄링은 각 스케줄링 주기마다 정확한 비율로 CPU를 배분한다.
시스템의 각 작업 프로세스는 보폭을 가지고 있다.
보폭은 자신이 가지고 있는 추첨권 수에 반비례하는 값이다.
임의의 큰 값을 각자의 추첨권 개수로 나누어 보폭을 계산할 수 있다.
stride = (A large number) / (the number of tickets of the process)
프로세스가 실행될 때마다 pass라는 값 (= counter)을 보폭만큼 증가시켜 얼마나 CPU를 사용하였는지를 추적한다.
스케줄러는 보폭과 pass 값을 사용하여 어느 프로세스를 실행시킬지 결정한다.
가장 작은 pass 값을 가진 프로세스를 선택한다.
프로세스를 실행시킬 때마다 pass 값을 보폭만큼씩 증가시킨다.
current = remove_min(queue); // pass 값이 최소인 클라이언트로 선택
schedule(current); // 자원을 타임 퀀텀만큼 선택된 프로세스에게 할당
current−>pass += current−>stride; // 다음 pass 값을 보폭 값을 이용하여 갱신
insert(queue, current); // 다시 큐에 저장한다.
- 예시
임의의 큰 숫자 = 10,000 일 경우, 각 프로세스에 할당된 추첨권은 다음과 같다고 가정했을 때 보폭 값은 다음과 같다.
| Process | Tickets | Stride |
|---|---|---|
| A | 100 | 100 |
| B | 50 | 200 |
| C | 250 | 40 |
C는 5번, A는 2번, B는 1 번만 실행되었다.
이 횟수는 각자 가진 추첨권의 개수 250, 100, 50과 정확히 비례한다.
각자의 pass 값은 모두 0에서 시작한다.
처음에는 pass 값이 같기 때문에 아무 프로세스나 실행될 수 있다.
임의로 A를 선택했다고 가정하자.
- A가 실행된다.
- 타임 슬라이스만큼 실행되고 종료될 때 pass 값을 100으로 갱신한다.
- B가 실행되고 해당 pass 값이 200으로 갱신된다.
- C를 실행하고, pass 값은 40으로 갱신된다.
- 이 시점에서 알고리즘은 가장 작은 pass 값을 가진 C를 선택하고 80 으로 갱신한다 (C의 보폭은 40이다).
- C가 다시 실행되고 (아직 최소 pass 값) 120 으로 갱신된다.
- A가 실행되고 200으로 갱신된다 (이제 B와 같아진다).
- C가 두 번 더 실행되고 pass 값은 160을 거쳐 200으로 갱신된다.
이 시점에서 모든 pass 값은 다시 같아지게 되고 이런 선택 과정이 계속 반복된다.
그런데도 추첨 스케줄링을 사용하는 이유
- 추첨 스케줄링은 프로세스 당 상태 정보가 필요 없다.
- CPU 사용 현황, pass 값 등을 유지할 필요가 없다.
- 추첨 스케줄링에서는 새 프로세스를 쉽게 추가할 수 있다.
보폭 스케줄링의 경우, pass 값이 만약 0 으로 지정된다면 CPU를 독점하게 될 것이다.
새 프로세스를 추가할 때, 새로운 프로세스가 가진 추첨권의 개수, 전체 추첨권의 개수만 갱신하고 스케줄한다.
The Linux Completely Fair Scheduling (CFS)¶
Operating System Examples - Scheduling Chapter 5.6,
IBM Developer
Arm Linux Kernel Hacks : [리눅스커널] 스케줄링: CFS 스케줄러를 이루는 주요 개념 알아보기
7강 - CFS
Linux Scheduler – CFS and Latency (sched_min_granularity_ns and sched_latency_ns) | oakbytes
-
Non-fixed timeslice.
→ CFS assigns process’s timeslice a proportion of the processor. -
Priority
Enables control over priority by using nice value. -
Efficient data structure
Use red-black-tree for efficient search, insertion and deletion of a process.
개념¶
n개의 process에게 각각 1/n process time 제공
특정 시간 안에 n개의 프로세스가 모두 동일한 시간 동안 실행
프로세스를 무한히 작은 시간 단위로 스케줄링
-
ex) 두 프로세스를 10ms동안 스케줄 할 때
unix - 5ms씩 수행
cfs - 10ms동안 두 프로세스를 각각 50%씩 동시에 실행 -
예제
ABCD 프로세스 중 CD 프로세스가 완료된 상태일 경우
Define The Scheduler Period Factor¶
-
sched_min_granularity_ns (lower bound)
- minimum time a task will be be allowed to run on CPU before being pre-empted out.
- Ensure that not too much time is spent in scheduling overhead, When there are too many process running.
- By default, it is set to 4ms. So by default, any task will run atleast 4ms before getting pre-empted out.
-
sched_latency_ns
- cfs가 설정한 가장 작은 스케줄링 단위 (최소 얼만큼 수행하겠다의 정수값의 레이턴시)
- By default, this is set to 20ms.
- the period in which all run queue tasks are scheduled atleast once.
- process’s timeslice = sched_latency / the number of process
- cfs가 설정한 가장 작은 스케줄링 단위 (최소 얼만큼 수행하겠다의 정수값의 레이턴시)
-
Calculating Schedule Latency
How does scheduler period depend onsched_latency_nsandsched_min_granularity_ns?
If number of runnable tasks does not exceedsched_latency_ns/sched_min_granularity_ns
scheduler period =sched_latency_ns
else
\(\(scheduler\;period (smallest\;time\;slice) = (number\;of\;processes) * sched\_min\_granularity\_ns\)\)
Example – In Linux system with default values, there are two processes, both busy waiting.
What will be the time slice of each task?
By default, sched_latency_ns = 20ms and sched_min_granularity_ns = 4ms
\(\(Time \;slice = scheduling \;period * {task’s \;weight \over total \;weight \;of \;tasks \;in \;the \;run \;queue}\)\)
Number of running tasks = 2
Weight of each task will be same. Hence (task’s weight/total weight of tasks in the run queue) will be 1/2
Hence time slice will be 20ms * 0.5 or 10ms
What happens when there are 20 such busy wait processes?
Ideally, each task should get 1 ms (=20ms * 1/20). But this is less than sched_min_granularity_ns.
sched_min_granularity_ns decides the minimum time a task will run.
By default, sched_min_granularity_ns is set to 4ms.
So in the case of 20 busy wait processes, each process will run for 4ms before it is preempted.
Nice Value¶
- nice는 time slice 대신 processor time 비율의 가중치 계산(퍼센티지)에 사용
A nice value is assigned to each task.- CFS enables controls over process priority.
- Nice parameter is integer value and can be set from
-20to+19 - The nice value is mapped to a weight (value is not important)
- eg. - 20 is mapped to 88761m 0 is mapped to 1024
- Lower nice value indicates a higher relative priority.
- Tasks with lower nice values receive a higher proportion of CPU processing time than tasks with hisher nice values.
- The default nice value is
0

\(\quad\)
The general idea is that
- Every process that changes nice value up by one level gets 10% less CPU power.
- Every process that changes nice value down by one gets 10% more CPU power
- The mapping from nice values to weights uses an array
- The array contains one entry for each nice level.
- The multiplier between the entries is 1.25
\(\quad\)
- Time Slice Calculation
- a targeted latency (TL):
- an interval of time during which every runnable task should run at least once.
(= cfs가 설정한 가장 작은 스케줄링 단위 (최소 얼만큼 수행하겠다의 정수값의 레이턴시)) - Linux에서는 20ms (sched_latency_ns, 시스템마다 정해져있다)
- ex) targeted latency가 20ms이면
- 2개의 작업이 있으면 - 각각 10ms씩 수행 (priority와 무관)(nice값 같음)
- 20개의 작업이 있으면 - 각각 1ms씩 수행
- 40개의 작업이 있으면 - 각각 0.5ms씩 수행
- an interval of time during which every runnable task should run at least once.
- Time slice for a \(task_i = TL * W_i / (Sum\,of\,all\,W_i)\)
\(\quad\) \(W_i\) (가중치): \(task_i\) 의 nice 값이 변경된 값 (nice, weight에 대한 table이 존재한다.)
\(\quad\)
- a targeted latency (TL):
- Time Slice Calculation Example
- Targeted latency = 20 ms
- Two tasks, \(t_1\) and \(t_2\), with nice values of 0
- The weight value for nice 0 is 1,024
- The share for each task is \(1024/(1024+1024) = 0.5\)
and thus each task will have a “time slice” of 10 ms
\(\quad\)
- Time Slice Calculation Example 2
- Targeted latency = 20 ms
- Two tasks, \(t_1\) and \(t_2\), with nice values of 0 and 5 respectively
- The weight value for nice 0 is 1,024 and the wight for nice 5 is 335
- The share for task \(t_1\) is \(1024/(1024+335) = 0.75\) and thus
- task \(t_1\) will have a “time slice” of 0.75*20 = 15 ms
- The share for task \(t_2\) is \(335/(1024+335) = 0.25\)
- task \(t_2\) will have a “time slice” of 20*0.25 = 5 ms
\(\quad\)
- Picking the next process
- Pick process with the weighted minimum runtime so far
- The virtual run time (vruntime) of a task is the actual runtime weighted by its niceness
- The value of vruntime is used by the scheduler to determine the next process to run
- Process with the smallest vruntime is selected to run next
\(\quad\)
-
vruntime (Virtual Runtime, 가상 실행 시간)
task(i)가 i/o를 기다리기 위해서 cpu에서 나오거나 time slice를 모두 소모해서 cpu에서 추출되면 변경된 vruntime를 가지게 된다.
scheduler가 호출될 때마다 현재 수행중인 task의 vruntime을 갱신한다.
task마다 있는 가상 수행시간으로, nice값이 크면 클수록 실제 시간보다 빠르게 지나간다 (실행시간이 작다.)- High nice values should result in less CPU time allocated to a process
→ 이런 경우 가상적으로 20ms 수행되게 느껴지도록 해주는 것 - This implies that vruntime cannot be the same as the real runtime
- Denote how long the process has been executing.
- Per-process variable.
- Increase in proportion with physical (real) time when it runs.
- CFS will pick the process with the lowest vruntime to run next.
- High nice values should result in less CPU time allocated to a process
-
Virtual Runtime Example
\(\quad\)Assume a process runs for 200 milliseconds
\(\quad\)\(\quad\)Nice value = 0: vruntime will be 200 milliseconds
\(\quad\)\(\quad\)Nice value < 0 : vruntime will be less than 200 milliseconds
\(\quad\)\(\quad\)Nice value > 0 : vruntime will be greater than 200 milliseconds -
Calculating vruntime
- Let \(runtime_i\) represent the amount of time spent using the CPU when a process has the CPU
- vruntime is incremented by
- \[vruntime_i = vruntime_i +{ runtime_i * weight_0 \over weight_i}\]
- where \(weight_0\) is the weight of \(nice\;value_0\)
- \(weight_i\) is the weight of \(nice\;value_i\)
-
- We refer to \(weight_0 /weight_i\) as the decay factor
- Weights of nice values are precomputed to avoid runtime overhead
\(\quad\)
- CFS Example Weights
| Nice Value | Weight | Decay Factor |
|---|---|---|
| - 5 | 3121 | 1024/3121 = 0.33 |
| -1 | 1277 | 1024/1277 = 0.80 |
| 0 | 1024 | 1024/1024 = 1 |
| 1 | 820 | 1024/820 = 1.24 |
| 5 | 335 | 1024/335 = 3.05 |
-
Using vruntime Example
- Assume two tasks \(t_1\) and \(t_2\) with
- nice values of 0 and 5 respectively
- \(vruntime_0\) and \(vruntime_1\) are initially zero
- Decay factors of 1 and 3.05 respectively
- Assume \(t_1\) runs for 200 milliseconds and t 2 runs for 100 milliseconds which is followed by a lot of other tasks
- vruntime 0 is 200 milliseconds
- vruntime 1 is 305 milliseconds
- \(t_1\) will be selected before \(t_2\) for execution
- Let’s say that t 1 runs again for 200 milliseconds; \(vruntime_0\) is now 400 milliseconds
- \(t_2\) will now be selected before \(t_1\) for execution
- Assume two tasks \(t_1\) and \(t_2\) with
Efficiently find the process with minimum virtual runtime. (\(O(logn)\))
The key for each node is the vruntime of the corresponding task.
To pick the next task to run, simply take the leftmost node.
This node is pointed to by a variable to reduce traversals
Dealing with I/O and Sleeping Processes¶
- Avoid the situation where some process monopolizes the CPU, if porcess have significantly small vruntime after sleeping.
- Set the vruntime of process to the minimum value found in tree when it wakes up.
- Process that sleep for short periods of time frequently do not ever get their fair share of the CPU.
Tip: Processes vs. threads
Linux incorporates process and thread scheduling by treating them as one in the same.
A process can be viewed as a single thread, but a process can contain multiple threads that share some number of resources (code and/or data).
7. 요약¶
비례 배분 스케줄링의 개념
추첨권 스케줄링
보폭 스케줄링
추첨권 스케줄링은 무작위성 (randomness) 을 사용한다.
보폭 스케줄링은 같은 목적을 결정적 방법으로 달성한다.
- CPU 스케줄러로서 널리 사용되고 있지 않는 이유
1. 입출력과 맞물렸을 때, 제대로 동작하지 않는다.
2. 추첨권 할당이라는 어려운 문제가 미해결 상태 ex) 브라우저에 얼마나 추첨권을 할당해야 하는가?
범용 스케줄러 (앞서 언급한 MLFQ 그리고 다른 유사 Linux 스케줄러 등)는 그러한 문제를 더 직관적으로 해결해서 씀
비례 배분 스케줄러는 추첨권 할당량을 비교적 정확하게 결정할 수 있는 환경에서 유용하게 사용된다.
예를 들어, 가상화 데이터 센터에서 Windows 가상 머신에 CPU 사이클의 1/4을 할당하고 나머지는 Linux 시스템에 할당하고 싶은 경우 비례 배분이 간단하고 효과적이다.
작성일 : 2023년 4월 2일






