Esercizio - shortest-first job scheduling, proprietà SJF e sottostruttura (esercitazione greedy, es. 10.2)
In questa pagina 3
Testo (esercitazione sul paradigma greedy, dispense del corso di Algoritmi per l'Ingegneria, Ing. Informatica UniPD). Un job è un programma da eseguire su una macchina . Si ha una collezione di job , ciascuno con tempo di esecuzione su . Si chiede un ordine di esecuzione (scheduling), cioè una corrispondenza biunivoca , per cui i job vengono eseguiti nell'ordine .
Sotto lo scheduling il tempo di attesa dell'-esimo job eseguito è la somma dei tempi dei job eseguiti prima, e si vuole minimizzare il tempo di attesa cumulativo (equivalente a minimizzare l'attesa media ).
Si dimostri la proprietà Shortest-Job First (SJF): per qualsiasi scheduling ottimo vale cioè il primo job eseguito è sempre di durata minima. Si dia poi l'algoritmo e la proprietà di sottostruttura ottima.
Passo 1: una formula per il costo
Il tempo del job eseguito in posizione compare nell'attesa di tutti i job eseguiti dopo, cioè delle posizioni , che sono . Quindi (L'ultimo job pesa con : non fa aspettare nessuno.) Il primo job ha peso , il secondo , e così via: i job eseguiti prima contano di più, ed è per questo che conviene mettere avanti quelli brevi. La formula è la base di tutto il resto.
Esempio. per . Nell'ordine le attese sono e (con la formula: ). Nell'ordine (durate ) le attese sono e ().
Passo 2: la proprietà SJF
Dimostrazione per assurdo con scambio (cut-and-paste). Sia ottimo e si supponga che non soddisfi SJF: e non è di durata minima. Esiste allora un job con più breve, , eseguito in una posizione : .
Si costruisce scambiando e :
Si confrontano le attese con :
- : entrambe .
- : la somma contiene la posizione ma non la posizione (perché ). Rispetto a compare al posto di :
- : la somma contiene entrambe le posizioni e , scambiate: gli addendi sono gli stessi, in ordine diverso per due di essi. .
Poiché , c'è almeno un indice () con diminuzione stretta, e in totale (la diminuzione è per ciascuno degli indici , cioè volte). Questo contraddice l'ottimalità di .
Osservazione: la proprietà vale per ogni ottimo (versione più forte della scelta greedy "esiste un ottimo"). Con tempi uguali possono esserci più ottimi, tutti con primo job di durata minima.
Passo 3: l'algoritmo e la sottostruttura ottima
Se si vede la scelta di come scelta greedy (Paradigma greedy - scelta golosa, sottostruttura e selezione delle attivitàIl paradigma greedy compie subito una scelta localmente migliore (scelta greedy), pulisce l'istanza (clean-up) e risolve l'unica sottoistanza residua, con ricorsione di coda eliminabile; il codice è facile, la correttezza no e richiede due proprietà, la scelta greedy (esiste un ottimo che la contiene) e la sottostruttura ottima (cut-and-paste), da cui la correttezza segue per induzione. Caso di studio: la selezione delle attività, con l'algoritmo del primo che finisce, correttezza completa, complessità Theta(n) dopo l'ordinamento e controesempi per le scelte greedy sbagliate.Paradigma greedy - scelta golosa, sottostruttura e selezione delle attività →), la SJF dice che essa è un job di durata minima. Non c'è clean-up: la residua è semplicemente l'insieme degli altri job, . Ripetendo la scelta, lo scheduling che ne esce si ottiene ordinando i job per durata non decrescente: è l'indice dell'-esimo job della sequenza ordinata. Il codice si riduce a una chiamata a una routine di ordinamento (Algoritmi di ordinamentoSelection sort e insertion sort (quadratici, con invarianti), merge sort (divide et impera, Theta(n log n)), quick sort (caso pessimo quadratico, medio n log n), heap sort (in loco, Theta(n log n)), ordinamento senza confronti per chiavi intere in un intervallo piccolo, limite inferiore Omega(n log n) per gli algoritmi basati su confronti.Algoritmi di ordinamento →): costo .
SJF_SCHEDULE(t)
ordina gli indici 1..n per t non decrescente // O(n log n)
pi(i) <- indice del job in posizione i dell'ordine
return piSottostruttura ottima. Sia ottimo (conterrà la scelta greedy) e sia , con , lo scheduling dei job successivi, cioè dell'istanza residua. Il tempo di attesa di ogni job della residua, sotto , è quello sotto diminuito di , perché il primo job non c'è più. I job della residua sono , quindi Il primo termine non dipende da : se non fosse ottimo per la residua, sostituendolo con uno scheduling migliore (cut-and-paste) si avrebbe per l'istanza principale un costo minore di , assurdo. Quindi è ottimo per la residua.
Correttezza. Per induzione sul numero di job: per (o ) lo scheduling vuoto (o banale) è ottimo; per lo scheduling ordinato inizia con un job di durata minima (SJF), prosegue con lo scheduling ordinato della residua, ottimo per ipotesi induttiva, e per la formula sopra ha costo .
Una seconda lettura. Dalla formula si vede che si accoppiano i pesi decrescenti con i tempi: la somma è minima quando i pesi grandi vanno ai tempi piccoli (disuguaglianza del riordinamento), cioè con tempi non decrescenti. È lo stesso risultato per un'altra strada.
Tutte le affermazioni (formula del costo, SJF per ogni ottimo, sottostruttura, ottimalità dell'ordine per durata) sono state verificate con Python generando tutte le permutazioni per su 2000 istanze casuali. Lo stesso criterio, visto dal punto di vista di un sistema operativo (attesa media, versione preemptive), è in Scheduling della CPU - FCFS, SJF, priorità e round robinLo scheduler della CPU sceglie tra i processi pronti quello a cui dare il core (il dispatcher esegue il cambio, con latenza di dispatch); lo scheduling è non preemptive (il processo tiene la CPU finché termina o si blocca) o preemptive (la CPU gli può essere tolta, con rischio di race condition); i criteri sono utilizzo della CPU e throughput (da massimizzare), tempo di attesa, di turnaround (completamento meno arrivo) e di risposta (da minimizzare); FCFS è semplice ma soffre dell'effetto convoglio (esempio 24, 3, 3: attesa media 17 contro 3); SJF è ottimo per l'attesa media ma richiede la lunghezza del prossimo burst, stimata con la media esponenziale tau(n+1) = alfa t(n) + (1-alfa) tau(n); SRTF è la versione preemptive (esempio con attesa media 6,5 contro 7,75); round robin dà a ciascuno un quanto q e nessuno attende più di (n-1)q; la priorità causa starvation, risolta con l'aging; code multilivello e a feedback (MLFQ) combinano le politiche.Scheduling della CPU - FCFS, SJF, priorità e round robin →.
Versione ripasso
- Problema: job con tempi ; ordine ; attesa ; si minimizza .
- Formula: (il job in posizione fa attendere gli successivi). Esempio : ordine dà , ordine per durata () dà .
- SJF per ogni ottimo : . Prova per assurdo: se e con , , si scambia e ; per l'attesa diventa , per non cambia; il totale scende di .
- Algoritmo: ordinare per non decrescente, . Scelta greedy = job più breve, clean-up vuoto, residua = gli altri job (Paradigma greedy - scelta golosa, sottostruttura e selezione delle attivitàIl paradigma greedy compie subito una scelta localmente migliore (scelta greedy), pulisce l'istanza (clean-up) e risolve l'unica sottoistanza residua, con ricorsione di coda eliminabile; il codice è facile, la correttezza no e richiede due proprietà, la scelta greedy (esiste un ottimo che la contiene) e la sottostruttura ottima (cut-and-paste), da cui la correttezza segue per induzione. Caso di studio: la selezione delle attività, con l'algoritmo del primo che finisce, correttezza completa, complessità Theta(n) dopo l'ordinamento e controesempi per le scelte greedy sbagliate.Paradigma greedy - scelta golosa, sottostruttura e selezione delle attività →).
- Sottostruttura: ; se non fosse ottimo per la residua, con cut-and-paste si migliorerebbe . Correttezza per induzione su .
- Lettura alternativa: pesi decrescenti accoppiati ai tempi crescenti (riordinamento). Versione da sistema operativo in Scheduling della CPU - FCFS, SJF, priorità e round robinLo scheduler della CPU sceglie tra i processi pronti quello a cui dare il core (il dispatcher esegue il cambio, con latenza di dispatch); lo scheduling è non preemptive (il processo tiene la CPU finché termina o si blocca) o preemptive (la CPU gli può essere tolta, con rischio di race condition); i criteri sono utilizzo della CPU e throughput (da massimizzare), tempo di attesa, di turnaround (completamento meno arrivo) e di risposta (da minimizzare); FCFS è semplice ma soffre dell'effetto convoglio (esempio 24, 3, 3: attesa media 17 contro 3); SJF è ottimo per l'attesa media ma richiede la lunghezza del prossimo burst, stimata con la media esponenziale tau(n+1) = alfa t(n) + (1-alfa) tau(n); SRTF è la versione preemptive (esempio con attesa media 6,5 contro 7,75); round robin dà a ciascuno un quanto q e nessuno attende più di (n-1)q; la priorità causa starvation, risolta con l'aging; code multilivello e a feedback (MLFQ) combinano le politiche.Scheduling della CPU - FCFS, SJF, priorità e round robin →.
- Errori tipici: contare invece di come peso del primo job; scrivere nello scambio (deve essere : è il più breve); dimostrare solo "esiste un ottimo con il job minimo" quando si chiede "ogni ottimo"; dimenticare che con tempi uguali gli ottimi sono più d'uno.