CPS 110 CPU scheduling Landon Cox February 7

  • Slides: 42
Download presentation
CPS 110: CPU scheduling Landon Cox February 7, 2008

CPS 110: CPU scheduling Landon Cox February 7, 2008

Switching threads ê What needs to happen to switch threads? 1. Thread returns control

Switching threads ê What needs to happen to switch threads? 1. Thread returns control to OS thread_yield ê For example, via the “yield” call 2. OS chooses next thread to run 3. OS saves state of current thread FIFO ê To its thread control block 4. OS loads context of next thread ê From its thread control block 5. Run the next thread swapcontext

Scheduling goals 1. Minimize average response time ê Elapsed time to do a job

Scheduling goals 1. Minimize average response time ê Elapsed time to do a job (what users care about) ê Try to maximize idle time ê Incoming jobs can then finish as fast as possible 2. Maximize throughput ê Jobs per second (what admins care about) ê Try to keep parts as busy as possible ê Minimize wasted overhead (e. g. context switches)

Scheduling goals 3. Fairness ê Share CPU among threads equitably ê Key question: what

Scheduling goals 3. Fairness ê Share CPU among threads equitably ê Key question: what does “fair” mean? Job 1 Job 2 Needs 100 seconds of CPU time

What does “fair” mean? ê How can we schedule these jobs? ê Job 1

What does “fair” mean? ê How can we schedule these jobs? ê Job 1 then Job 2 ê 1’s response time = 100, 2’s response time = 200 ê Average response time = 150 Job 1 Job 2 ê Alternate between 1 and 2 Needs 100 time = 2’s Needs 100 ê 1’s response time = 200 seconds of ê Average response time = time 200 CPU time CPU

Fairness ê First time thinking of OS as government ê Fairness can come at

Fairness ê First time thinking of OS as government ê Fairness can come at a cost ê (in terms of average response time) ê Finding a balance can be hard ê What if you have 1 big job, 1 small job? ê Response time proportional to size? ê Trade-offs come into play

FCFS (first-come-first-served) ê FIFO ordering between jobs ê No pre-emption (run until done) ê

FCFS (first-come-first-served) ê FIFO ordering between jobs ê No pre-emption (run until done) ê Run thread until it blocks or yields ê No timer interrupts ê Essentially what you’re doing in 1 t ê Adding interrupt_disable for safety ê (for auto-grader pre-emption)

FCFS example ê Job A (100 seconds), Job B (1 second) A arrives and

FCFS example ê Job A (100 seconds), Job B (1 second) A arrives and starts A done (t=0) B arrives (t=0+) (t=100) B done (t=101) ê Average response time = 100. 5 seconds

FCFS ê Pros ê Simplicity ê Cons? ê Short jobs stuck behind long ones

FCFS ê Pros ê Simplicity ê Cons? ê Short jobs stuck behind long ones ê Non-interactive ê (for long CPU job, user can’t type input)

Round-robin ê Goal ê Improve average response time for short jobs ê Solution to

Round-robin ê Goal ê Improve average response time for short jobs ê Solution to FCFS’s problem ê Add pre-emption! ê Pre-empt CPU from long-running jobs ê (timer interrupts) ê This is what most OSes do

Round-robin ê In what way is round robin fairer than FCFS? ê Makes response

Round-robin ê In what way is round robin fairer than FCFS? ê Makes response times job length ê In what way is FCFS fairer than round robin? ê First to start will have better response time ê Like two children with a toy ê Should they take turns? ê “She’s been playing with it for a long time. ” ê Should first get toy until she’s bored? ê “I had it first. ”

Round-robin example ê Job A (100 seconds), Job B (1 second) A arrives and

Round-robin example ê Job A (100 seconds), Job B (1 second) A arrives and starts A swapped A runs out A done (t=0) (t=1) (t=2) (t=101) B arrives B done B starts (t=0+) (t=2) (t=1) Does round robin always provide lower response times than FCFS? ê Average response time = 51. 5 seconds

Round-robin example 2 ê Job A (100 seconds), Job B (100 second) A arrives

Round-robin example 2 ê Job A (100 seconds), Job B (100 second) A arrives and starts A swapped A runs out A done (t=0) (t=1) (t=2) BBarrives swapped B starts out (t=0+) (t=2) (t=199) B done (t=200) Any hidden costs that we aren’t counting? Context switches ê Average response time = 199. 5 seconds

Round-robin example 2 ê Job A (100 seconds), Job B (100 second) A done

Round-robin example 2 ê Job A (100 seconds), Job B (100 second) A done (t=199) B done (t=200) What would FCFS’s avg response time be? 150 seconds ê Average response time = 199. 5 seconds

Round-robin example 2 ê Job A (100 seconds), Job B (100 second) A done

Round-robin example 2 ê Job A (100 seconds), Job B (100 second) A done (t=199) B done (t=200) Which one is fairer? It depends … ê Average response time = 199. 5 seconds

Round-robin ê Pros ê Good for interactive computing ê Better than FCFS for mix

Round-robin ê Pros ê Good for interactive computing ê Better than FCFS for mix of job lengths ê Cons ê Less responsive for uniform job lengths ê Hidden cost: context switch overhead ê How should we choose the time-slice? ê Typically a compromise, e. g. 10 microseconds ê If context switch is. 1 us, only waste 1% of CPU

Course administration ê Only half of the groups are done with 1 d ê

Course administration ê Only half of the groups are done with 1 d ê (none have submitted the thread library yet) ê Deadline ê Project 1 is due in two weeks ê (each group has 3 late days) ê “Drop-dead” deadline is Sunday, Feb. 24 th ê Unsolicited advice ê If possible, try to avoid using your late days ê Only use your late days if you absolutely need to ê Start Projects 2 and 3 as early as possible

Project 1 ê Garbage collecting threads // simple network server while (1) { int

Project 1 ê Garbage collecting threads // simple network server while (1) { int s = socket. accept (); thread_create (sat_request, s); } ê Do not want to run out of memory ê What needs to be (C++) “deleted”? ê Any state associated with the thread (e. g. stack, TCB)

Project 1 ê Two key questions: ê When can a stack be deleted and

Project 1 ê Two key questions: ê When can a stack be deleted and by whom? ê When can a stack be deleted? ê Only after the thread has finished its “work” ê Work = function passed to thread_create, thread_libinit ê Who definitely cannot delete a thread’s stack? ê The thread itself! ê Try deleting the stack you are running on … ê So which thread should delete the stack?

Project 1 ê Hint: don’t use uc_link ê Only use swapcontext to switch threads

Project 1 ê Hint: don’t use uc_link ê Only use swapcontext to switch threads ê Anyone want to guess why? ê What can you say about state of interrupts? ê Interrupts are enabled inside “work” function ê After it exits, interrupts must be disabled ê Tricky to guarantee this using uc_link ê Can get an interrupt while switching to uc_link

Project 1 ê What makes swapcontext simpler? ê uc_link loads threads outside of your

Project 1 ê What makes swapcontext simpler? ê uc_link loads threads outside of your lib ê Calls to swapcontext are explicit ê “Keep everything in front of you” ê Any other Project 1 questions?

STCF and STCF-P ê Idea ê Get the shortest jobs out of the way

STCF and STCF-P ê Idea ê Get the shortest jobs out of the way first ê Improves short job times significantly ê Little impact on big ones 1. Shortest-Time-to-Completion-First ê Run whatever has the least work left before it finishes 2. Shortest-Time-to-Completion-First (Pre-emp) ê If new job arrives with less work than current job has left ê Pre-empt and run the new job

STCF is optimal ê (among non-pre-emptive policies) ê Intuition: anyone remember bubble sort? Job

STCF is optimal ê (among non-pre-emptive policies) ê Intuition: anyone remember bubble sort? Job B Start Job A Finish What happened to total time to complete A and B?

STCF is optimal ê (among non-pre-emptive policies) ê Intuition: anyone remember bubble sort? Job

STCF is optimal ê (among non-pre-emptive policies) ê Intuition: anyone remember bubble sort? Job A Job B Start What happened to the time to complete A? What happened to the time to complete B? Finish

STCF is optimal ê (among non-pre-emptive policies) ê Intuition: anyone remember bubble sort? Job

STCF is optimal ê (among non-pre-emptive policies) ê Intuition: anyone remember bubble sort? Job A Start Job B Finish What happened to the average completion time?

STCF-P is also optimal ê (among pre-emptive policies) ê Job A (100 seconds), Job

STCF-P is also optimal ê (among pre-emptive policies) ê Job A (100 seconds), Job B (1 second) A arrives and starts A runs (t=0)(t=1) A done (t=101) done B arrives Band pre(t=1) empts ê Average (t=0+)response time = 51 seconds

I/O ê What if a program does I/O too? while (1) { do 1

I/O ê What if a program does I/O too? while (1) { do 1 ms of CPU do 10 ms of I/O } ê To scheduler, is this a long job or a short job? ê Short ê Thread schedular only care about CPU time

STCF-P ê Pros ê Optimal average response time ê Cons? ê Can be unfair

STCF-P ê Pros ê Optimal average response time ê Cons? ê Can be unfair ê What happens to long jobs if short jobs keep coming? ê Legend from the olden days … ê IBM 7094 was turned off in 1973 ê Found a “long-running” job from 1967 that hadn’t been scheduled ê Requires knowledge of the future

Knowledge of the future ê You will see this a lot in CS. ê

Knowledge of the future ê You will see this a lot in CS. ê Examples? ê Cache replacement (next reference) ê Banker’s algorithm (max resources) ê How do you know how much time jobs take? ê Ask the user (what if they lie? ) ê Use the past as a predictor of the future ê Would this work for banker’s algorithm? ê No. Must know max resources for certain.

Grocery store scheduling ê How do grocery stores schedule? ê Kind of like FCFS

Grocery store scheduling ê How do grocery stores schedule? ê Kind of like FCFS ê Express lanes ê Make it kind of like STCF ê Allow short jobs to get through quickly ê STCF-P probably wouldn’t fly

Final example ê Job A (CPU-bound) ê No blocking for I/O, runs for 1000

Final example ê Job A (CPU-bound) ê No blocking for I/O, runs for 1000 seconds ê Job B (CPU-bound) ê No blocking for I/O, runs for 1000 seconds while (1) { do 1 ms of CPU do 10 ms of I/O } ê Job C (I/O-bound)

Each job on its own A: 100% CPU, 0% Disk B: 100% CPU, 0%

Each job on its own A: 100% CPU, 0% Disk B: 100% CPU, 0% Disk C: 1/11 CPU, 10/11 Disk CPU Disk Time

Mixing jobs (FCFS) A: 100% CPU, 0% Disk B: 100% CPU, 0% Disk C:

Mixing jobs (FCFS) A: 100% CPU, 0% Disk B: 100% CPU, 0% Disk C: 1/11 CPU, 10/11 Disk CPU Disk How well would FCFS work? Not well.

Mixing jobs (RR with 100 ms) A: 100% CPU, 0% Disk B: 100% CPU,

Mixing jobs (RR with 100 ms) A: 100% CPU, 0% Disk B: 100% CPU, 0% Disk C: 1/11 CPU, 10/11 Disk CPU Disk How well would RR with 100 ms slice work?

Mixing jobs (RR with 1 ms) A: 100% CPU, 0% Disk B: 100% CPU,

Mixing jobs (RR with 1 ms) A: 100% CPU, 0% Disk B: 100% CPU, 0% Disk C: 1/11 CPU, 10/11 Disk CPU Disk How well would RR with 1 ms slice work? Good Disk utilization (~90%) Good principle: start things that can be parallelized early A lot of context switches though …

Mixing jobs (STCF-P) A: 100% CPU, 0% Disk B: 100% CPU, 0% Disk C:

Mixing jobs (STCF-P) A: 100% CPU, 0% Disk B: 100% CPU, 0% Disk C: 1/11 CPU, 10/11 Disk B? CPU Disk How well would STCF-P work? (run C as soon as its I/O is done) Good Disk utilization (~90%) Many fewer context switches Why not run B here? When will B run? When A finishes

Real-time scheduling ê So far, we’ve focused on average-case ê Alternative scheduling goal ê

Real-time scheduling ê So far, we’ve focused on average-case ê Alternative scheduling goal ê Finish everything before its deadline ê Calls for worst-case analysis ê How do we meet all of our deadlines? ê Earliest-deadline-first (optimal) ê Used by students to complete all homework assignments ê Used by professors to juggle teaching and research ê Note: sometimes tasks get dropped (for both of us)

Earliest-deadline-first (EDF) ê EDF ê Run the job with the earliest deadline ê If

Earliest-deadline-first (EDF) ê EDF ê Run the job with the earliest deadline ê If a new job comes in with earlier deadline ê Pre-empt the current job ê Start the next one ê This is optimal ê (assuming it is possible to meet all deadlines)

EDF example ê Job A ê Takes 15 seconds ê Due 20 seconds after

EDF example ê Job A ê Takes 15 seconds ê Due 20 seconds after entry ê Job B ê Takes 10 seconds ê Due 30 seconds after entry ê Job C ê Takes 5 seconds ê Due 10 seconds after entry

EDF example A: takes 15, due in 20 B: takes 10, due in 30

EDF example A: takes 15, due in 20 B: takes 10, due in 30 C: takes 5, due in 10 A B C 0 20 30 35 40 45 50 55

Next time ê Asynchronous programming ê Fewer stacks, less CPU overhead ê Harder to

Next time ê Asynchronous programming ê Fewer stacks, less CPU overhead ê Harder to program (? ) ê Wrapping up threads/concurrency

Threads/concurrency wrapup ê Concurrent programs help simplify task decomposition ê Relative to asynchronous events

Threads/concurrency wrapup ê Concurrent programs help simplify task decomposition ê Relative to asynchronous events ê Concentrate all the messiness in thread library ê Cooperating threads must synchronize ê To protect shared state ê TO control how they interleave ê We can implement the abstraction of many CPUs on one CPU ê Deadlock ê Want to make sure that one thread can always make progress ê CPU scheduling ê Example of how policy affects how resources are shared ê Crucial trade-off: efficiency vs. fairness