CPU Scheduling

Processes alternate between using the CPU (called a CPU burst) and doing I/O.

Two categories of processes:

  1. I/O bound processes - short CPU bursts e.g., iteractive, file processing
  2. CPU bound processes - scientific calculation processes
Generally we want to favor I/O bound processes to get them doing I/O while the CPU bound processes use the CPU. A good scheduler seeks a balance between these conflicting goals:
  1. Fairness - each process gets fair share of the CPU
  2. Efficiency - keep the CPU and I/O devices as busy as possible
  3. Response time - minimize response time for interactive users
  4. Turnaround time - minimize time batch users must wait for output
  5. Throughput - maximize the number of processes/jobs to complete per time
Timer can by used by the OS to periodically regain control of the CPU. Preemptive scheduling - stopping a runnable process and running another; used by most OSs In nonpreemptive scheduling a running process must "voluntarily" reliquish the CPU by terminating or doing I/O. Priority scheduling algorithms - each process has a priority and the highest priority process runs

Priorities might be dynamic or static, but usually there is some aging scheme to prevent starvation.

Process Priority could be based on:

  1. External priority - system processes have higher priority, then faculty processes, then student processes
  2. Internal criteria

Possible scheduling algorithms

FCFS (First Come First Serve) - strict FIFO queue that is nonpreemptive.

Round Robin - cycle between each process giving each a CPU time quantum (a fixed amount of time); especially good for interactive or time-sharing processes

Quantum size must be chosen carefully

Shortest Job First (SJF) - give CPU to process those next CPU burst is the shortest

Optimal w.r.t. the average waiting time of a process, i.e., it's useful to improve turnaround time of batch jobs or response-time of interactive jobs

Problem: we don't know how long a process' next CPU burst will be, but we can predict it from previous CPU bursts. One approach is to exponentially average previous CPU bursts as

Estimate first burst as t1 (maybe use the system average)

Measure first CPU burst t1

Prediction for second CPU burst: t2 = at1 + (1 - a)t1, where 0 < a < 1

Measure second CPU burst t2

Prediction for third CPU burst: t3 = at2 + (1 - a)t2

...

Prediction for (n+1)st CPU burst: tn+1 = atn + (1 - a)tn,

Recall that tn was recursively based on previous measured CPU bursts:

tn+1 = atn + (1 - a)tn

= a(atn-1 + (1 - a)tn-1) + (1 - a)tn = a2tn-1 + a(1 - a)tn-1 + (1 - a)tn

= a2(atn-2 + (1 - a)tn-2) + a(1 - a)tn-1 + (1 - a)tn

= a3tn-2 + a2(1 - a)tn-2 + a(1 - a)tn-1 + (1 - a)tn

...

= (1 - a)[tn + atn-1 + a 2 tn-2 + a 3 tn-3 + ... + a n-1 t1] + a nt1

Since 0 < a < 1, larger powers of a place less weight on older burst times.

e.g., a = ½ and n = 3 (so n+1 = 4)

t4 = ½ [t3 + ½ t2 + ¼ t1] + 1/8 t1 = ½ t3 + ¼ t2 + 1/8 t1 + 1/8 t1

Special cases:

If a = 0, tn+1 = tn (only use last CPU burst as a predictor).

If a = 1, tn+1 = t1 (don't use past history only system average).

If a = ½ , place ½ weight on last CPU burst and ½ weight on older runs.

(easy to implement when a = ½ or ¼ (or any power of 2)

Often multiple queues are used with different priority processes, e.g.,

Multilevel Feedback Queue - queues each have their own priority and scheduling algorithm, but there is some method to:

Lottery scheduling - useful to allocate a resource (such as the CPU) with varying allocations

Idea: OS holds a lottery 50 times a second to see which process can use the CPU

The winning process uses the CPU for 20 msec. For example,

We'd expect that a process would get the CPU proportional to its fraction of all tickets.

Cooperating processes could exchange tickets to increase chance of running. For example, a server might be allocated zero tickets, but a client holding 30 tickets might transfer them to the server.

Multiple-Processor Scheduling

In a heterogeneous system, a process will only execute on compatible processor(s).

Several homogeneous processors allow load sharing via common ready queue.

Implementation options:

  1. master-slave arrangement: a master processor delegates work to slave processors
  2. distributed scheduling: each processor removes (/adds) next process from a common ready queue.

Evaluating New Scheduling Algorithms

View Document Return to top of page