CPU Scheduling은 왜 필요할까? 사실, 이제까지는 cpu scheduling을 전제로 이야기를 쭉 해와서, 너무 당연하게 느껴졌을 수 있다. 하지만 process하나가 cpu를 잡으면 종료될 때 까지 cpu를 놓지 않게 할 수도 있는 것이다.
앞에서 언급했듯이 실제로는 cpu scheduling을 fifo 방식으로 하지 않는다. 하나의 process가 종료되고 그제서야 다른 process가 실행되는 방식이라거나, io가 완료될 때 까지 그냥 process가 blocked되어버린 상태로 cpu가 놀면 사람 입장에서는 답답한 것도 있고, 또 효율적이지 않다.
따라서 cpu를 더 효율적으로 놀리기 위해 scheduling이 필요하다.
용어 정리를 하고 가자
- CPU Schedulier
- ready 상태의 process 중에서 이번에 cpu를 줄 process를 고른다
- 얘는 운영체제 안에 있는 코드이다
- Dispatcher
- CPU를 줄 process가 결정된 상태에서, 실제로 그 친구한테 넘겨준다.
- context switch를 발생시키는 것
- 적절한 분류인지는 모르겠지만, cpu scheduling이 필요한 경우는 process에 다음과 같은 상태 변화가 있는 경우이다.
1. running → blocked (ex) io 요청의 경우)
2. running → ready (ex) timer에 의한 interrupt)
3. blocked → ready (ex) io 완료에 따른 interrupt)
4. terminate
1, 4 : nonpreemptive = 강제로 빼앗지 않고, 자진 반납하는 경우
2, 3 : preemptive = 강제로 빼앗는 경우
분류보다는 preemptive라는 단어에 조금 더 집중하라고 한다. 자주 등장하니까
CPU burst, IO burst
모든 Process들은 CPU를 돌리는 구간과, io요청을 날리고 이를 기다리는 구간으로 나뉜다.
전자를 cpu burst, 후자를 io burst라고 한다.
cpu scheduling에서는 cpu를 누구에게 줄 것인지, 줬다면 얼마동안 쓸 수 있게 해줄지를 결정하는 것이 관건이다.
보통 선점형, 비선점형(preemptive, non-preemptive)으로 나뉜다.
가능하면 많이 cpu를 놀릴 수록 좋은 것
cpu utilization
throughput
빨리 얻어서 빨리 끝나면 좋은 것일 것
turnaround time
waiting time
response time
말 그대로 먼저 온 것을 먼저 처리하는 방법이다.
진짜 별거 없다. 말 그대로 선착순
1, 3, 5000초의 실행 시간을 요구하는 processe들이 있다고 하자.
P3-P2-P1순으로 실행되는 경우 waiting time W3=0, W2=5000, W1=5003초,
P1-P2-P3순으로 실행되는 경우 waiting time W1=0, W2=1, W3=4초로
극명하게 큰 차이가 난다.
❕이렇게 긴 process가 먼저 cpu를 잡아 뒤의 짧은 process들이 다뤄지지 못하는 것을 convoy effect라고 한다.
CPU 사용시간이 가장 짧은 process를 먼저 처리하는 방법이다.
전체적으로 꽤 행복한 결과가 나오는 방법
✅ 두 가지로 나뉜다.
Nonpreemptive
Preemptive
average waiting time이 가장 짧은 방법
✅ 다음과 같은 문제점이 있다.
✅ 두번째 문제점은 추정을 통해 극복 가능하다.
Exponential Averaging 기법으로 추정한다. 미래 추정을 위해 과거를 일정 비율로 반영하는 기법이다.
: n번째 cpu burst, n번째 cpu burst 추정시간
위 식은 재귀적으로 풀어진다. 이 좌, 우변에 있는 것만 봐도 알 수 있다. 직접 써내려가보면 쉽게 확인 가능할 것
결론적으로는 n번째 실제 cpu burst에 가장 큰 가중치를 두고, 과거의 cpu burst들에 조금 더 낮은 가중치를 둬가며 그 것들을 모두 합쳐 n+1번째 cpu burst를 추정하게 된다. 물론 를 잘 구해야 정확하게 추정되겠지만 ㅋㅋㅋ..
우선순위가 가장 높은 process에게 cpu를 주는 방법
✅ 마찬가지로, Preemptive와 nonpreemptive가 다르다.
preemptive인 경우, 새로 ready queue에 들어온 process 중 더 우선순위가 높은 것이 있다면 cpu를 내어주고, nonpreemptive인 경우 일단 쭉 cpu를 가져간 후 해당 process가 종료되면 다음에 실행할 process를 물색한다.
✅ 우선순위는
보통 정수로 표현하고, 작은게 더 우선순위를 높게 가져간다. 물론 설계하기 나름
사실 SJF도 우선순위 스케쥴링으 종류 중 하나이다. 실행시간을 우선순위로 설정하면 그게 바로 SJF가 된다.
✅ 다음과 같은 문제점이 있다.
✅ 우선순위 수정해가며 극복 가능하다.
Aging이라는 기법이 있다. 물론 여기서만 쓰는 기법은 아니고, 경험상 이런 애들은 무언가 추정을 할 때 시간 도메인이 달려있으면 자주 쓰는 기법인거 같더라
다양한 방법이 있을 수도 있겠는데, 간단하게는 그냥 특정 상수를 매 차례마다 곱해줌으로써 우선순위를 낮추면 된다.
Process에 cpu를 줄 때, 할당 시간(time quantum)을 함께 주며, 할당 시간이 채워지면 cpu를 빼앗는다. 당연히 preemptive 방식
Response time이 빨라진다는 장점이 있다.
✅ 다음과 같은 특징이 있다.
할당 시간은 10~100ms정도가 적당하다고 알려져있다고 한다.
실행 시간이 동일한 process들이 여러개 들어오면, 모두 waiting time을 길게 가져가다가, 마지막에 한꺼번에 종료되는 상황이 발생한다. 한꺼번에 종료되는 것, 혹은 하나라도 종료되는 것 중 무엇이 좋느냐에 대한 대답은 애매하다. 경우에 따라 다를 것. 어쨋든 이런 상황도 발생한다는 것이다.
결국 Round Robin의 최대 장점은 reponse time이 빠르다는 것
multilevel queue의 예시
ready queue를 여러개로 분할해서 우선순위가 다른 queue를 여러개 두는 방법
✅ 다음과 같은 것들을 고려해야할 것이다.
✅ 아래와 같은 방법으로 설계해볼 수 있겠다. 물론 설계하기 나름이다. 정말 다양한 조합이 있을 수 있겠다. 아래는 예시일 뿐
ready queue를 여러개로 분할해서 우선순위가 다른 queue를 여러개 두며, process가 한 queue에 종속되지 않고, 서로 다른 queue에 배정될 수 있도록 하는 방법
✅ 다음과 같은 것들을 고려해야할 것이다.
여러 방법이 있을 수 있겠지만 보통 위와 같은 방법을 쓴다고 한다.
CPU 사용시간이 짧은 친구들한테 우선순위를 크게 주는 알고리즘이다.
CPU 사용시간이 긴지 짧은지 예측할 필요 없이 짧은게 우대받는다.
위에서는 processor가 하나인 상황, 별다른 제약 조건이 없는 상황에서 process들을 처리하는 방법을 때에 따라 preemptive, nonpreemptive 정도로만 나눠 다뤘다. 그 외의 경우에서는 scheduling해야할 대상이 또 어떤게 있고, 어떻게 scheduling할 수 있는지 간략하게 알아보자
CPU가 여러개 있다면?
Deadline이 있는 job, 정해진 시간 안에 꼭 실행되어야만 하는 job을 real-time job이라고 한다. 이런 친구들을 scheduling하려면?
보통 이런 친구들은 그때그때 scheduling하는게 아니라,
미리 offline등에서 scheduling해서 deadline이 보장되도록 적재적소에 배치하는 것처럼, 상황과 특성에 맞게 먼저 구성을 마친 후 돌리는 방법을 쓴다.
생각나는가? user level thread와 kernel level thread가 있었다.
user level thread의 경우 kernel 입장에서 thread가 존재하는지 모른다. 그냥 라이브러리의 도움을 받아 만든 thread이다.
알고리즘 성능을 평가하는 방법을 간략하게 알아보자.
개인적으로 이런건 간략하게 알아보는 정도로는 의미가 없다고 생각한다. 있다는 것은 인지하고, 필요할 때 잘 공부해서 잘 성능평가 해봐야하는거지. 근데 잘 하려면 잘 알아야한다 ㅠ
이론적으로 많이 쓰는 방법. 요즘에는 그냥 직접 만들어 돌려본다고
위 방법이 쉽지 않으니 시뮬레이션 돌려보는 것이다. factor들을 잘 캐치해야 신빙성있는 시뮬레이션이 될 것