이번 장에서는 시간을 최적화 하는 것보다는, 작업의 비율 배분에 초점을 맞춘 스케줄러를 알아볼 것이다.
비례 배분 (공정 배분, fair share): 반환시간이나 응답시간을 최적화하는 대신 스케줄러가 각 작업에게 CPU의 일정 비율을 보장하는 것
핵심 질문: 어떻게 CPU를 정해진 비율로 배분할 수 있는가?
추첨권(티켓): 프로세스가 할당받아야 할 자원의 몫
참고로 추첨 스케줄링은 할당량을 "확률적"으로 달성한다.
- 추첨권을 확률만큼 주고, 여러번 실행 시키면, 해당 확률에 수렴하게 됨
- 정확히 75%, 25%가 나오지 않으나, 수렴함
결정론적(Deterministic)으로 할당시키는 방법은
- 예를 들어, 3번 A 실행시키고 한번은 B 실행 <- 이를 반복
사용자가 추첨권을 자신의 화폐 가치로 추첨권을 자유롭게 할당할 수 있도록 허용하는 기법.
프로세스가 일시적으로 추첨권을 다른 프로세스에게 넘겨줄 수 있는 기법
프로세스가 일시적으로 자신이 소유한 추첨권의 수를 늘리거나 줄일 수 있는 기법
구현이 간단하다.
// 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" 는 당첨자를 가리킴: 당첨자가 실행될 수 있도록 준비
winner
를 랜덤으로 추출counter
에 현재 가리키고 있는 작업이 가지고 있는 추첨권의 개수를 누적합counter
가 winner
보다 커지면 당첨! winner
가 300이라면counter = 100
counter = 150
counter = 400
-> 당첨자 발견일반적으로 리스트가 내림차순으로 정렬했을 때 가장 효율적이게 됨
(추첨권 많은 순으로 앞에 위치, 그녀석들이 당첨될 확률이 높은 것은 당연)
예를 들어 두개의 작업(A,B)이 같은 개수의 추첨권을 가지고 있고, 실행 시간(R)도 같다고 하자.
목표: 두 작업을 거의 동시에 종료시키는 것
불공정 지표(U) = (첫 작업 종료시간) / (두번째 작업 종료 시간)
작업의 길이가 1일 때
작업의 길이가 2일 때
이런식으로 작업의 길이를 늘려가면 동시에 끝날 확률이 점점 늘어난다. 즉, 불공정 정도가 1에 가까워지며 균등하게 작업이 배분이 된다.
따라서 작업시간이 충분히 길어야 추첨 스케줄러가 원하는 결과에 가까워진다는 것을 알 수 있다.
그렇다면 추첨권은 작업에게 어떻게 분배해야 하는가?
-> "추첨권 할당 문제"는 미해결 문제
무작위성을 이용한 스케줄러는 단순하고, 나름 정확하다.
하지만 정확한 비율은 보장할 수 없고, 짧은 기간만 실행되는 경우 더 그렇다.
따라서 결정론적 공정 배분 스케줄러인 "보폭 스케줄링"이 고안되었다.
보폭 스케줄링(stride scheduling)
pass
라는 값을 보폭만큼 증가시켜 얼마나 CPU를 사용했는지를 추적current = remove_min(queue); // pass 값이 최소인 작업 선택
schedule(current); // 자원을 타임 슬라이스만큼 선택된 프로세스에게 전달
current->pass += current->stride; // 다음pass값을 보폭 값을 이용하여 갱신
insert(queue, current); // 다시 큐에 저장
보폭 스케줄링은 각 스케줄링 주기마다 정확한 비율로 CPU를 배분한다.
그럼 왜 추첨 스케줄링을 쓰는지?
비례 배분 스케줄링: 스케줄러가 각 작업에게 CPU의 일정 비율을 보장하는 것