무한봉쇄나 기아상태를 해결하기 위한 방법

5.1 Basic Concepts

CPU의 코어가 1개라고 하자. 이러면 당연히 한번에 하나의 태스크만 실행될 수 밖에 없다. 만약 순차적으로 모든 일이 진행된다고 해보자.

어... 그림에서 볼 수 있듯이 I/O 대기나 인터럽트가 생기게 된다고 해보자. 그걸 하나 하나 다 기다리려고 하면 뒤 태스크는 손가락만 빨 수 밖에 없고, 결국 효율성이 떨어질 수 밖에 없다.

당연히 효율성을 높이려면 이런 상황에 도래했을 때 태스크를 넘겨줘야 효율성을 높일 수 있을 것이다.

CPU-I/O Burst Cycle

프로세스 실행은 CPU 실행과 입출력 대기의 사이클로 구성된다. 즉, 두 state 중 하나에 머물러 있다는 것이다.

프로세스 실행은 CPU Burst로 시작된다. 이어서 I/O Burst가 발생하고, 이어서 또 다른 CPU Burst가 발생하고... 이러다가 마지막에 종료를 알리는 System Call과 함께 끝난다.

당연히 입출력 중심의 프로그램은 I/O Burst의 시간이 길테고, 반대의 경우도 있을 것이니, 이런 점을 잘 고려해 설계해야 할 것이다.

CPU Scheduler

CPU가 idle 상태가 되면, OS는 Ready Queue에 있는 프로세스 중 하나를 선택해 실행해야 한다. 당연히 선택 절차는 Short-term Scheduler에 의해 수행될 것이다.

참고로, Ready Queue는 FIFO 구조가 아닐 수도 있다. (이후 배울 Scheduling Algorithm에 따라 달라질 것이다.) 또한, Ready Queue에 들어있는 친구들은 프로세스 그 자체가 아니라, PCB 형태의 레코드들이다.

Preemptive/Non-preemptive Scheduling

CPU 스케줄링 결정은 다음과 같은 상황에서 발생할 것이다.

  • 한 프로세스가 running state에서 wait state로 바뀔때 (ex. I/O 요청,. 자식 프로세스의 종료를 위해 wait 하는 상태)
  • 프로세스가 running state에서 ready state로 바뀔때 (ex. 인터럽트 발생)
  • 프로세스가 waiting state에서 ready state로 바뀔때 (ex. I/O 종료)
  • 프로세스가 종료될 때

1/4번이라면 당연히 프로세스가 바뀌어야 한다. 2/3은 바꿀수도 있고, 아닐수도 있겠지?

만약 특정 스케쥴링 알고리즘이 1/4번의 경우에만 교환이 이뤄진다면, 우리는 비선점(Non-preemptive)라고 하며, 1/2/3/4번 모두 발생한다면 선점(Preemptive)이라고 한다.

전자의 경우엔 일단 CPU가 한 프로세스에 할당되면 방출되기 전 까지 혼자서 독차지를 한다. 후자의 경우엔 그렇진 않을 것이다. 다만, 후자의 경우엔 공유 자원에 대한 Race Condition (자세한 내용은 Ch.06에...)이 발생할 수 있다.

선점 이야기를 조금 더 해보자. System Call을 처리하는 동안, 커널은 이미 한 프로세스를 위한 활동으로 바쁠 수 있다. 그런데 이런걸 하고 있는데 선점되어 프로세스의 주도권이 빼앗긴다면? 뭔가 문제가 많이 생길 것이다. 그래서 UNIX를 포함한 몇몇 운영체제는 Context Switch를 하기 전 System Call이 종료되거나 I/O에 따른 Blocking이 발생하기까지 기다리곤 한다.

Dispatcher

CPU 스케쥴링 기능에 포함된 또 다른 요소로, CPU의 제어를 Short-term Scheduler가 선택한 프로세스에게 주는 모듈이며, 다음과 같은 작업을 포함한다.

  • 특정 프로세스에서 다른 프로세스로 Context Switching이 발생할 때
  • 커널 모드에서 사용자 모드로 전환 (Dispatcher는 커널 모드임...)
  • 프로그램을 다시 시작하기 위해 사용자 프로그램의 특정 부분으로 jump

Dispatcher는 Context Switching 마다 호출되므로, 가능한 빨리 수행되어야 한다. Dispatcher가 하나의 프로세스를 정지하고 다른 프로세스의 수행을 시작하는 데까지 소요 되는 시간을 디스패치 지연 (Dispatch latency)라고 한다.

5.2 Scheduling Criteria

상황에 맞는 스케쥴링 알고리즘을 사용하기 위해선, 각각의 서로 다른 특성을 이해하고 현재 상황에 맞는 알고리즘을 선택해야 한다.

  • CPU Utilization: 가능한 CPU를 활용하고 싶을 것이다. 실제 시스템에선 40~90% 정도를 기준으로 잡는다.
  • throughout: CPU가 프로세스를 수행하느라 바쁘다는 것은 곧 작업을 수행하고 있다는 것이다. 단위 시간당 완료된 프로세스를 작업량 측정의 단위로 사용할 수 있는데, 이를 처리량(throughout) 이라고 한다.
  • turnaround time: 각각의 프로세스 입장에서 볼 때, 자기 자신이 빨리 끝나는게
  • waiting time: 결과적으로 스케쥴링 알고리즘은 프로세스가 실행하거나 입출력하는 시간의 양에 영향을 끼치지 않고, 대기시간에만 영향을 준다. (대기시간: Ready Queue에서 대기하는 시간의 총 합)
  • response time: interactive system에서, 처리하는데 소요되는 시간은 중요하지 않을 수 있다. 사용자의 요구가 많은 경우엔, 하나의 요구를 제출한 후 첫 응답이 나오는데 까지 걸리는 시간을 따지는 경우도 있다.

5.3 Scheduling Algorithm

우리는 알고리즘의 효율성을 설명하기 위해 간트 차트 (Gantt Chart)를 사용할 것이다. (버스트 시간이 모두 채워져야 Terminate 되기 때문에, 시간의 흐름에 따른 현재 버스트 상태인 프로세스를 보여주는 그래프이다.)

First-Come, First-Served (FCFS)

가장 간단한 방법으로, CPU를 먼저 요청하는 프로세스가 CPU를 먼저 할당받는다. 구현은 일반적인 FIFO 큐를 활용하면 쉽게 구현할 수 있다.

구현도 쉽고, 코드도 짧지만, 대기시간이 한없이 길어질 수 있다.

프로세스가 P1, P2, P3이 있고, Burst Time이 각각 24, 3, 3이라고 하자.

P1 → P2 → P3 순으로 가면, 대기 시간은 각각 0, 24, 27이고 평균 대기시간은 17ms이다.

P2 → P3 → P1 순으로 간다면, 대기 시간은 각각 6, 0, 3이고, 평균 대기시간은 3ms이다. 따라서 FCFS Queue에 들어가는 순서에 따라 시간이 크게 변할 수 있다.

예시를 하나만 보자. CPU-bound 프로세스 1개와 I/O-Bound 프로세스 여러개가 있다고 하자. CPU-bound 먼저 들어가면 긴 시간을 한참동안 기다리다가, I/O 요청을 위해 I/O Queue로 이동하게 되면, 다른 프로세스들은 빠르게 움직인다. (I/O Burst가 기니까) 그러다 CPU-bound 프로세스가 Ready Queue에 가게 되면 또 한없이 기다려야 한다... → Convey Effect (다른 프로세스들이 하나의 긴 프로세스가 CPU를 양도하기를 기다리는 것.)

Shortest-Job-First (SJF)

각 프로세스에 CPU burst 길이를 남기도록 하고, 이용 가능해지면 Burst 시간이 가장 짧은 프로세스를 할당한다.

즉, P1, P2, P3, P4의 Burst Time이 6, 8, 7, 3이면,

다음과 같이 할당할 수 있다.

실제로 증명을 하면 최소의 평균 대기 시간을 가진다는 것을 알 수 있다. (그리디 알고리즘)

현실은... CPU burst 시간을 어떻게 알 수 있냐는 것이다. 그래서 이전 CPU burst 시간을 기록해서 이후의 시간을 추측한다. 즉, 단기 CPU 스케쥴링에서는 SJF를 사용하기에 현실적으로 어려움이 있고, 장기 CPU 스케쥴링에서 많이 사용된다.

Tn을 n번째 CPU burst의 길이라고 하면, 0 < a < 1에 대해서,

 이라는 공식이 성립하는데, t는 최근의 정보를, τ은 과거의 역사를 저장한다. 매개변수 a의 값은 최근의 값과 이전 값의 가중치를 제어한다. 식을 최대한 확장하면,

이라는 공식이 나올 것이다. 0 < a < 1 이므로, 더해지는 값은 점점 갈 수록 감소하는 경향을 띌 수 밖에 없다.

또한, SJF는 선점/비선점형이 모두 가능한데, 만약 새로운 프로세스가 들어올때 현재 실행되고 있는 프로세스와 비교해서 CPU burst 시간이 짧다면, 선점형에 한해 현재 실행되고 있는 프로세스를 빼앗을 것이다.

Priority Scheduling

사실 SJF는 우선순위 스케쥴링의 일부이다. 당연히 우선순위 스케쥴링은 우선순위를 기준으로 하여 높은걸 먼저 배치할 것이다.

우선순위의 요건은 다양한데, 시간제한, 메모리 요구, 파일 수, 평균 I/O burst, 평균 CPU burst...

단점이라면, 무한 봉쇄(indefinite blocking)기아 상태(starvation)이 발생할 수 있다는 것이다. 만약 우선순위가 낮은 프로세스가 있다면, CPU를 할당받지 못하고 계속해서 뒤쪽에 머물러 있을 것이다.

이런 문제를 해결하기 위해 노화(aging) 기법을 사용하는데, 오랫동안 시스템에서 대기하는 프로세스들의 우선순위를 점진적으로 증가시키는 방법이다.

Round-Robin Scheduling

특별히 시분할 시스템을 위해 설계된 알고리즘이다. FCFS와 유사하지만, 시스템이 프로세스들 사이를 옮겨 다닐 수 있도록 선점성이 추가된다.

시간 할당량 (time quantum) 또는 시간 조각 (time slice)라고 하는 작은 단위의 시간을 정의하고, Ready Queue를 Circular Queue로 만들어서 작동한다.

스케쥴러는 하나의 프로세스를 선택해 일정 시간 이후에 인터럽트를 걸도록 타이머를 설정하고, Dispatch한다.

프로세스가 작동하다가 시간 할당량을 초과하면 현재 프로세스가 끝나지 않았음에도 다음 프로세스로 넘어가기 때문에, 선점형으로 볼 수 있다.

시간 할당량이 매우 크면 사실상 FCFS와 같아지고, 매우 적으면 과도한 Context Switching이 발생하기 때문에 오버헤드에 의한 성능 저하가 발생할 수 밖에 없다. 즉, 시간 할당량은 최소한 Context Swiching에 걸리는 시간보단 길어야 할 것이다.

Multilevel Queue Scheduling

프로세스들을 몇몇 그룹으로 분리하여 활용하기 위한 스케쥴링 알고리즘. (ex. foreground process/background process)

Ready Queue를 별도의 큐로 분류한다. 프로세스를들을 메모리 크기나 우선순위, 메모리등으로 분류하여 하나의 Ready Queue에 영구적으로 배정한다. 이때, 각각의 Ready Queue에는 서로 다른 알고리즘을 부여할 수 있다.

또한, 큐와 큐 사이의 스케쥴링도 존재해야 하는데, 일반적으로는 고정적인 우선순위의 선점형 알고리즘을 활용한다.

Multilevel Feedback Queue Scheduling

위에서 언급한 Multilevel Queue Scheduling의 경우, 프로세스가 큐를 바꾸지 않아 오버헤드가 상대적으로 적으나, 융통성이 적다.

위에서 우선순위 스케쥴링의 단점이었던 무한 봉쇄와 기아 상태가 발생할 수도 있으므로, 중간 중간에 우선순위가 다른 큐로 프로세스를 이동시킴으로써 그러한 단점을 해소할 수 있을 것이다.

설계중인 특성 시스템에 부합하도록 각각의 큐의 조건을 정의할 수 있고, 대응하기도 쉬우나 가장 좋은 스케쥴러로 동작하기 위해선 모든 매개변수들의 값을 선정해야 하므로 (큐의 수, 각각의 큐의 스케쥴링 알고리즘, 한 프로세스를 높은/낮은 우선순위를 갖고 있는 큐로 이동시키는 조건, 처음에 프로세스가 들어갈 큐를 결정할 조건...) 가장 복잡한 알고리즘이라는 단점도 있다.

5.4 Thread Scheduling

스레드는 어떻게 스케쥴링할까? 사실 스레드 스케쥴링은 라이브러리에 의해 실행되기 때문에, 위에서 이야기한 스케쥴링 알고리즘을 OS단에서 적용하지 않는다. 즉, OS는 커널 스레드만 신경 쓰면 될 문제이다.

이전 단원에서 다대일/다대다 모델에 대해 설명했는데, 이 경우 스레드 라이브러리는 사용자 수준 스레드를 사용 가능한 범위에서 스케쥴링 한다. 즉, 동일한 프로세스에 속한 스레드들이 CPU를 경쟁하기 때문에 스케쥴링 기법을 PCS(Process-contention score, 프로세스-경쟁 범위)라고 한다. 그러나 스케쥴링 한다고 해서 실제로 실행된다는 소리는 아니다. 왜냐하면 커널 스레드를 물리적인 CPU로 배정하기 위해 또 다른 스케쥴링을 진행해야 하기 때문이다. 커널이 어떤 커널 스레드를 스케쥴 할 지 결정하기 위해선 SCS(System-contention score, 시스템-경쟁 범위)을 사용한다.

당연히 일대일 모델을 사용하는 일반적인 운영체제는 SCS만 사용할 것 이다. 또한, PCS는 우선순위에 따라 행해지는 것이 일반적이나, 유저에 의해 우선순위가 조정될 수 있고 대부분의 스레드 라이브러리는 권한이 없다.

Pthread

POSIX Pthread Scheduling의 예를 보자.

#include <pthread.h> #include <stdio.h> #define NUM_THREADS 5 void *runner(void *param); int main(int argc, char *argv[]) { int i, scope; pthread_t tid[NUM_THREADS]; pthread_attr_t attr; pthread_attr_init(&attr); if(pthread_attr_getscope(&attr, &scope) != 0) fprintf(stderr, "Unable to get scheduling scope\n"); else { if(scope == PTHREAD_SCOPE_PROCESS) printf("PTHREAD_SCOPE_PROCESS"); else if(scope == PTHREAD_SCOPE_SYSTEM) printf("PTHREAD_SCOPE_SYSTEM"); else fprintf(stderr, "Illegal scope value.\n"); } pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); for(int i = 0; i < NUM_THREADS; i++) pthread_create(&tid[i], &attr, runner, NULL); for(int i = 0; i < NUM_THREADS; i++) pthread_join(tid[i], NULL); } void *runner(void *param) { pthread_exit(0); }

코드에서,

  • PTHREAD_SCOPE_PROCESS: PCS를 사용해서 스레드를 스케쥴 함.
  • PTHREAD_SCOPE_SYSTEM: SCS를 사용해서 스레드를 스케쥴 함.

위에서 말한 것 처럼 PCS를 사용하지 않고 SCS만 사용하기 때문에, (시스템 구조가 다르다면 모를까...) "PTHREAD_SCOPE_SYSTEM" 가 출력 될 것이다.

pthread_attr_(get/set)scope는 경쟁 범위 정책의 정보를 얻고 지정한다. (두번째 매개변수는 enum 형태의 *int)

5.5 Multi-Processor Scheduling

지금까지의 스케쥴링은 CPU가 1개일때의 이야기이다. 만약에 CPU가 여러개라면? 그럴땐 부하 공유(Load Sharing)이 가능해진다. 물론 스케쥴링 문제는 저것까지 고려해야 하기 때문에 매우 복잡해진다.

Approaches to Multuple-Processor Scheduling

크게 두가지 방법으로 나눠본다면, 하나는 비대칭 다중 처리(Asymmetirc Multiprocessing)라고 하여 하나의 처리기를 주 서버라고 부르고, 이것으로 하여금 모든 스케쥴링 결정과 I/O, 그리고 다른 시스템의 활동을 취급하게 하는 것을 말한다. 다만 주 서버에 문제가 생기면 전체 시스템에 병목현상이 발생할 수 있다.

다른 하나는 대칭 다중 처리 (Symmetric Multiprocessing, SMP)라고 하는데, 이 방식에서는 각자 독자적으로 스케쥴링 한다. 모든 프로세스는 공동의 Ready Queue에 있거나 각 프로세서 마다의 Ready Queue에 있어야 한다. 다만 이 경우엔 동시에 여러 프로세서가 공동 Ready Queue에 접근하는 일이 없도록 잘 프로그래밍 되어야 한다.

현대적인 OS는 모두 SMP를 지원하며, 나머지 내용도 SMP에 대한 내용이 주가 될 것이다.

Processor Affinity

프로세스가 실행중일때, 캐시는 뭘 하고 있을까?

고양이 이름 아님...

일단 프로세서에 의해 가장 최근에 접근된 데이터가 캐시 메모리에 적재될 것이다. 만약 프로세스가 한 프로세서 내부만 빙~빙~ 돈다면 문제가 없겠지만, 지금은 프로세서가 여러개이기 때문에 이동할 수도 있을 것이다. 그렇게 된다면 기존에 있던 곳의 캐시는 지우고, 새로 이주한 곳의 캐시는 새로 채워야 하는데, 이건 시간이 상대적으로 오래 걸리므로 최대한 같은 프로세서 내부에서 실행하려고 한다. 이것을 프로세서 친화성 (Processor Affinity) 라고 한다.

만약 OS가 동일한 프로세서에서 프로세스를 실행하려고 노력은 하지만 보장은 하지 않을때, 연성 친화성 (Soft Affinity)를 가진다고 한다. 이 경우 이주 하는 것이 가능은 할 것이다. 반면 Linux 같은 일부 시스템은 강성 친화성 (Hard Affinity)을 지원하는 System Call을 갖고 있는데, 이 호출을 통해 프로세스는 자신이 실행될 프로세서 집합을 명시할 수 있다. (물론 Linux는 Soft Affinity도 지원한다.)

Load Balancing

부하를 적절히 잘 나눠야 각각의 프로세서를 최대한 활용할 수 있다. 일반적인 로드 밸런싱은 Push Migration과 Pull Migration으로 나뉘어져 있다.

전자의 경우 특정 테스크가 각각의 로드를 감시하고 불균형일 경우 다른 곳으로 넘겨주는 것이고, 후자는 쉬고 있는 프로세서가 다른 일을 가져오는 것이다. 위에서 설명한 친화성을 파괴하지만, 필요에 따라 조절할 필요는 있다.

Multicore Processors

멀티코어의 경우 스케쥴링이 조금 더 복잡해진다. 메모리 멈춤 (Memory Stall)이라고 하여 프로세서가 메모리를 접근할 때 데이터의 가용을 기다리면서 대기 시간이 길어지는 것인데, 이는 캐시 미스를 포함한 다양한 원인 때문에 발생한다. 그래서 이를 해결하기 위해 각 코어에 여러개의 하드웨어 스레드를 할당하고 스레드가 번갈아가면서 실행되는 방식을 도입했다.

일반적으로 프로세서를 멀티스레딩화 하는데에는 두 방법이 있다. 하나는 Stall이 발생할 때 까지 한 프로세서에서 실행되다가 긴 대기 시간이 발생하면 명령어 파이프라인을 정리하고 채우는 방식이고, 다른 하나는 명령어 주기의 경계 처럼 세밀한 부분에서 교환을 시키는 바법이다.

5.6 Real-Time CPU Scheduling

실시간 OS에서 스케쥴링 할 때는 특별한 쟁점을 고려해야 한다.

Minimizing Latency

사건이 발생하면, 시스템은 가능한 빨리 그에 응답을 하고 그에 맞는 동작을 수행하여야 한다. 즉, 사건이 발생하면 시스템은 가능한 빨리 그에 응답을 하고 그에 맞는 동작을 수행하여야 한다. 레이턴시는 사건이 발생해서 그에 맞는 서비스가 수행될 때까지의 시간을 말한다.

일반적으로 사건이 다르면 그에 따른 레이턴시 역시 다르다. 레이턴시는 크게 두개로 나뉘는데, 이 것이 실시간 시스템의 성능을 제어한다.

  • 인터럽트 레이턴시: CPU에 인터럽트가 발생한 시점부터 해당 인터럽트 처리 루틴이 시작하기까지의 시간을 말한다. 일반적으로 인터럽트가 발생하면 OS는 수행 중인 명령어를 완수하고, 인터럽트의 종류를 결정한 뒤 ISR(Interrupt Service Routine)을 사용하여 인터럽트를 처리하기 전 수행 중인 프로세스의 상태를 저장해 놓아야만 한다. 여기서 ISR 수행 전 다른 처리를 하는 시간을 인터럽트 레이턴시라고 부른다.
  • 디스패치 레이턴시: 스케쥴링 디스패치가 하나의 프로세스를 블로킹하고 다른 프로세스를 시작하게 하는데 걸리는 시간을 말한다.

5.7 Operating System Example

늘 그랬듯이... Solaris와 Windows는 깔끔하게 넘긴다.

이전까지 LINUX 스케쥴링은 전통적인 UNIX 스케쥴링 알고리즘의 변형을 사용했으나, 이 알고리즘은 SMP를 염두에 두고 설계된것이 아니기 떄문에 멀티 프로세서를 잘 지원하지 못한다. 현재는 해당 문제를 해결한 CFS(Completely Fair Scheduler; 완벽한 공평 스케쥴러)가 디폴팅 스케쥴링 알고리즘이 되었다.

각 클래스 별로 특정 우선순위를 부여받는 스케쥴링 클래스에 기반을 두고 동작한다. 다른 스케쥴링 클래스를 사용하여 시스템과 프로세스의 요구조건에 따라 커널은 다른 스케쥴링 알고리즘을 수용할 수 있다.

CFS 스케쥴러는 상대 우선순위에 상응하는 시간 할당량의 길이가 정해져 있는 경직된 규칙을 사용하지 않고 각 태스크에 CPU 처리 시간을 할당한다. 즉, 특정한 수치 값을 가지는 것이 아니라 목적 레이턴시 값(Targeted Latency)을 찾는다. 이것은 다른 모든 수행 가능한 태스크가 적어도 한 번씩은 실행할 수 있는 시간 간격을 나타낸다. 해당 목적 레이턴시 값으로부터 CPU 시간의 비율이 할당된다.

CFS는 직접 우선수위를 할당하지 않고, 각 태스크 별로 vruntime이라는 변수에 태스크가 실행된 시간을 기록하여 가상 실행 시간을 유지한다. 이 가상 실행 시간은 태스크의 우선순위에 기반을 둔 감쇠 지수(Decay Factor)와 관련된다. 낮은 우선순위를 갖는 태스크는 높은 것과 비교하여 감쇠율이 높다. 즉, 실제 실행 시간보다 vruntime의 값이 더 큰 것이다.

그렇다면 이걸 어떻게 관리할까? → RBT를 쓴다! RBT에 태스크를 담아 vruntime 값을 기준으로 정렬한다. 만약 같은 우선순위를 가진 두 태스크가 있다고 가정하자. 하나는 입출력 중심이고 다른 하나는 CPU 중심 태스크이다. 이런 경우 전자는 추가의 입출력을 위하여 짧은 시간 실행되고 블로킹 되므로 실행 시간이 짧을 것이다. 결국, 입출력 중심 태스크의 vruntime 값은 CPU 중심 태스크의 값보다 작아지게 될 것이며, 우선순위가 올라가게 될 것이다. 이 상황에서 입출력 중심 태스크가 실행 가능하게 되면 현재 실행 중인 CPU 중심 태스크를 선점하게 된다.

5.8 Algorithm Evaluation

그래서 수많은 알고리즘 중에서 뭘 써야 할까? 각자의 시스템에 맞는 걸 쓰면 되겠지만, 그걸 어떻게 판단할 수 있을까? 먼저 시스템을 정의하고, 알고리즘을 선택하는데 사용할 기준을 정의해야 한다. 예를 들어,

  • 최대 응답 시간이 1초라는 제약 조건 하에 CPU의 이용률을 극대화한다.
  • 총 처리 시간이 전체 실행 시간에 평균적으로 선형 비례가 되도록 처리량을 극대화한다.

일단 기준이 정의되면, 평가하는 것은 그렇게 어렵지 않다.

Deterministic Modeling

결정론적 모델링은 사전에 정의한 특정 작업 부하를 받아들여 그 작업 부하에 대한 각 알고리즘의 성능을 정의한다. 즉, 이전에 앞에서 봤던 예시를 통해 평균 대기 시간을 계산하는 것이다.

단순하고 계산하기 빠르지만, 입력으로 정확한 숫자를 요구하고 그 응답도 해당 경우에만 적응된다는 문재점이 있다. 그래서 동일한 프로그램을 반복해 여러 번 실행하고, 프로그램의 처리 요구 사항들을 정확하게 측정 할 수 있는 경우엔 사용하면 좋을 것이다.

Queuing Model

현실적으로, 많은 시스템에서 실행되는 프로새스들은 날마다 변화하기 때문에 결정론적 모델링을 사용하기에 조금 어려운 감이 있다. 따라서 CPU와 입출력 버스트의 분포를 측정하여 근사 값을 계산한다. 일반적으로 이런 분포는 지수분포 형태를 띄고 있으며 평균에 의해 기술된다.

예를 들어, n을 평균 큐의 길이라고 하고, W를 큐에서의 평균 대기시간이라고 하자. λ를 새로운 프로세스들이 큐에 도착하는 평균 도착률 (ex. 1초에 3개의 프로세스)이라고 하면, W 시간 동안 λ*W 개의 새로운 프로세스들이 큐에 도착할 것이고, 일반적으로 큐를 떠나는 프로세스의 수는 도착하는 프로세스의 수와 같아야 할 것이다. 즉,

n=λWn = λW이 성립한다. (Little's formula)

스케쥴링 알고리즘을 비교하는데 유용하게 사용할 수 있으나 현재 분석할 수 있는 알고리즘과 분포의 부류가 상당히 제한되어 있다. 또한 다수의 독립된 가정을 해야하므로 실제 적용시에는 다른 결과를 내놓을 수 있다. 이러한 어려움 때문에 시스템의 근사치로 봐야하며, 연산된 결과의 정확성에는 의심의 여지가 있다.

Simulation

컴퓨터 시스템의 모델을 프로그래밍하고 특정 상황을 모델링 해서 시뮬레이션 할 수도 있을 것이다. 시뮬레이션 하는 시스템의 상황을 캡쳐링 할 수 있는 (프로세스 및 스케쥴러의 활동, 장치등...) 시뮬레이터를 활용해 성능을 파악한다. 결과는 가장 정확하겠지만 매우 많은 시간, 비용적 리스크가 따른다.

Toplist

최신 우편물

태그