Salta al contenuto
Note per Studenti Scheduling multiprocessore e real-time

Scheduling multiprocessore e real-time

In questa pagina 4

Gli algoritmi di 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 → pensano a una sola CPU e a processi senza scadenze. Qui si tolgono due ipotesi: i compiti hanno una scadenza (real-time) e i processori sono più di uno. Gli esercizi con numeri su Rate Monotonic ed EDF sono in Esercizio - Rate monotonic ed EDF su due compiti periodici (slide di scheduling).

Scheduling real-time

Molte applicazioni devono reagire a un evento in tempo breve: il freno antibloccaggio (ABS), i robot industriali, i sistemi di difesa. Il sistema operativo adatto è un RTOS (real-time operating system), tipico dei sistemi embedded (Sistemi operativi embedded e real-time per l'IoTUn sistema embedded è un dispositivo con elettronica e software per una funzione specifica, spesso con vincoli di tempo reale; i microcontrollori (8, 16 o 32 bit, KB di RAM, senza MMU, mW) formano i sistemi profondamente embedded dell'IoT, divisi dall'IETF in classi 0, 1 e 2; i sistemi embedded hanno kernel configurabile, boot loader e root file system costruiti su un host con cross-compilazione; si può adattare un OS esistente (embedded Linux, uClinux senza MMU, Buildroot, Yocto) o usare un OS dedicato (TinyOS a componenti ed eventi, RIOT a microkernel con scheduler a priorità fissa preemptive senza tick, FreeRTOS, Zephyr, Contiki-NG con protothread); l'IoT ha requisiti di memoria minima, hardware eterogeneo, rete a basso consumo, efficienza energetica, tempo reale e sicurezza; nel laboratorio con RIOT si crea una shell, si leggono i thread con ps, si creano thread con priorità e si sincronizzano con un mutex.Sistemi operativi embedded e real-time per l'IoT →).

La latenza di evento (event latency) è il tempo tra il momento in cui l'evento avviene e quello in cui viene servito. Due latenze la determinano:

latenza definizione
latenza di interrupt dall'arrivo dell'interrupt all'avvio della routine che lo serve (v. InterruptClassi di interruzioni; I/O guidato da interrupt; sequenza hardware e software di gestione con salvataggio del contesto sullo stack; identificazione della sorgente (linee multiple, polling, daisy chain, vettore); priorità e interruzioni annidate; eccezioni e modi in ARM.Interrupt →)
latenza di dispatch tempo che lo scheduler impiega a togliere il processo dalla CPU e a mettere in esecuzione quello critico

Due tipi di sistemi:

  • soft real-time: i compiti critici hanno la priorità più alta, ma non c'è garanzia su quando verranno eseguiti; serve almeno uno scheduling a priorità con prelazione;
  • hard real-time: un compito deve essere servito entro la scadenza; oltre alle condizioni del soft, bisogna dimostrare che le scadenze si rispettano.

Compiti periodici

Si considerano compiti che richiedono la CPU a intervalli regolari: ognuno ha un tempo di elaborazione (burst) tt, una scadenza dd e un periodo pp, con 0≤t≤d≤p0 \le t \le d \le p (spesso d=pd = p: finire prima dell'inizio del periodo successivo). La frequenza è 1/p1/p. L'utilizzo del compito è t/pt/p, quello dell'insieme è ∑ti/pi\sum t_i/p_i. Si pensi a un processo che legge un sensore o controlla i messaggi in arrivo. Il controllo di ammissione (admission control) decide se la scadenza può essere rispettata.

Priorità fisse: il controesempio e Rate Monotonic

Due compiti: P1P_1 con p1=50p_1 = 50, t1=20t_1 = 20; P2P_2 con p2=100p_2 = 100, t2=35t_2 = 35. Utilizzo: 20/50+35/100=0,40+0,35=75%20/50 + 35/100 = 0{,}40 + 0{,}35 = 75\%: sembra possibile. Ma se si dà priorità più alta a P2P_2, esso finisce a 35, poi parte P1P_1 che finisce a 55, dopo la sua scadenza (50): fallisce. La priorità va assegnata bene.

Definizione (Rate Monotonic, RMS). Nello scheduling Rate Monotonic la priorità (fissa, con prelazione) è l'inverso del periodo: periodo più breve, priorità più alta.

Qui p1<p2p_1 < p_2, quindi P1P_1 ha la priorità più alta:

t 0 .. 20 20 .. 50 50 .. 70 70 .. 75
CPU P1P_1 P2P_2 (30 unità) P1P_1 (nuovo periodo) P2P_2 (ultime 5)

P1P_1 finisce a 20 (≤50\le 50); P2P_2 parte a 20, a 50 ha fatto 30 unità e viene prelazionato dal nuovo P1P_1; riprende a 70 e finisce a 75 (≤100\le 100). Entrambe le scadenze sono rispettate.

RMS è ottimo tra gli algoritmi a priorità fissa, ma solo se l'utilizzo non supera il limite del caso peggiore per NN compiti:

Umax⁡(N)=N(21/N−1)N=2:0,828N=3:0,780N=4:0,757N→∞:ln⁡2≈0,693.U_{\max}(N) = N\left(2^{1/N} - 1\right) \qquad N=2: 0{,}828 \quad N=3: 0{,}780 \quad N=4: 0{,}757 \quad N\to\infty: \ln 2 \approx 0{,}693.

Per l'esempio precedente 75%<82,8%75\% < 82{,}8\% e funziona. Un controesempio: p1=50p_1 = 50, t1=25t_1 = 25 e p2=80p_2 = 80, t2=35t_2 = 35, utilizzo 25/50+35/80=0,9375>0,82825/50 + 35/80 = 0{,}9375 > 0{,}828. Con RMS (P1P_1 ha priorità):

t 0 .. 25 25 .. 50 50 .. 75 75 .. 85
CPU P1P_1 P2P_2 (25 di 35) P1P_1 P2P_2 (ultime 10)

P2P_2 finisce a 85, dopo la scadenza 80: la scadenza è mancata. Superare il limite non implica sempre il fallimento (il limite è solo sufficiente), ma qui avviene.

Earliest Deadline First

Definizione (EDF). Nello scheduling Earliest Deadline First le priorità sono dinamiche: si esegue il compito con la scadenza più vicina. Vale anche per compiti non periodici. Le scadenze sono garantite finché l'utilizzo totale è inferiore al 100%.

Stesso esempio (25/50 e 35/80):

t 0 .. 25 25 .. 60 60 .. 85 85 .. 100 100 .. 125 125 .. 145
CPU P1P_1 (scad. 50) P2P_2 (scad. 80) P1P_1 (2a istanza, scad. 100) P2P_2 (2a istanza, scad. 160) P1P_1 (3a, scad. 150) P2P_2 (resto)
  • a t=50t=50 arriva la seconda istanza di P1P_1 (scadenza 100), ma P2P_2 ha scadenza 80: continua, e finisce a 60;
  • a t=80t=80 arriva la seconda istanza di P2P_2 (scadenza 160): P1P_1 (scadenza 100) ha la precedenza e finisce a 85;
  • a t=100t=100 la terza istanza di P1P_1 (scadenza 150) prelaziona P2P_2 (scadenza 160): tutte le scadenze sono rispettate.

La prelazione avviene solo se la nuova scadenza è strettamente minore.

Ripartizione proporzionale

Si assegnano TT quote (shares) a tutti i processi; un'applicazione con NN quote (N<TN < T) riceve la frazione N/TN/T del tempo di CPU. Con T=100T = 100 e NA=50N_A = 50, NB=15N_B = 15, NC=20N_C = 20 ricevono il 50%, 15% e 20%. Un controllo di ammissione impedisce l'ingresso di un processo che non trova quote: un DD con ND=30N_D = 30 non entra, perché restano solo 100−50−15−20=15100 - 50 - 15 - 20 = 15 quote.

Scheduling con più processori

Con più CPU lo scheduling è più complesso. Le architetture: CPU multicore, core multithread, sistemi NUMA, multiprocessori eterogenei.

SMP e code di pronti

Nel multiprocessing simmetrico (SMP) ogni processore si schedula da solo. I thread pronti possono stare in una coda comune (richiede sincronizzazione sull'accesso alla coda) oppure ogni processore può avere la propria coda privata (più comune, ma richiede il bilanciamento del carico).

Core multithread

Si mettono più core nello stesso chip (più veloce e a basso consumo) e più thread hardware per core (chip multithreading, CMT; Intel lo chiama hyperthreading): un sistema a 4 core con 2 thread hardware ciascuno è visto dal sistema come 2×4=82 \times 4 = 8 processori logici. Il vantaggio: quando un thread ha uno stallo di memoria (memory stall, la CPU è molto più veloce della memoria, v. Gerarchia di memoria e principio di localitàCaratteristiche delle memorie (posizione, capacità, unità di trasferimento, metodo di accesso, prestazioni, volatilità); compromesso costo-capacità-velocità e gerarchia a livelli; località temporale e spaziale con esempi; hit, miss e tempo medio di accesso con calcolo svolto.Gerarchia di memoria e principio di località →) il core passa a un altro thread hardware invece di restare fermo. Gli algoritmi sono a due livelli: il sistema sceglie quale thread software eseguire su un processore logico; il core sceglie quale thread hardware eseguire.

Bilanciamento del carico

In un sistema SMP bisogna mantenere tutti i processori occupati: il bilanciamento del carico (load balancing) distribuisce il lavoro in modo uniforme.

  • push migration: un compito controlla periodicamente il carico di ogni processore e spinge i thread da quello sovraccarico agli altri;
  • pull migration: un processore inattivo tira a sé un thread in attesa da uno occupato.

Affinità al processore

Quando un thread ha girato su un processore, la sua cache contiene i dati che ha usato (warm cache, cfr. Memoria cacheBlocchi, linee ed etichette; scomposizione dell'indirizzo; associazione diretta, completamente associativa e associativa a insiemi con calcolo dei campi; politiche di rimpiazzo (LRU, FIFO, casuale); politiche di scrittura (write-through, write-back con bit sporco, write-allocate); dimensione del blocco; cache multilivello e separate; come ridurre i miss; quesiti sui campi dell'indirizzo.Memoria cache →): spostarlo la fa perdere. Si parla di affinità al processore (processor affinity). Il bilanciamento può contraddirla.

tipo significato
soft affinity il sistema cerca di tenere un thread sullo stesso processore, ma non garantisce
hard affinity il processo specifica l'insieme di processori su cui può girare

Nei sistemi NUMA uno scheduler NUMA-aware assegna la memoria vicina alla CPU in cui gira il thread; Linux, Windows e FreeBSD recenti lo sono.

Esempi: Linux e Windows

  • Linux usa per default il Completely Fair Scheduler (CFS), in via di sostituzione con EEVDF (Earliest Eligible Virtual Deadline First). Fa bilanciamento del carico ed è NUMA-aware. Un dominio di scheduling è un insieme di core bilanciabili tra loro, organizzati in base a ciò che condividono (per esempio la cache): si evita di far migrare i thread tra domini.
  • Windows usa uno scheduling a priorità con prelazione: gira il thread di priorità più alta, finché si blocca, finisce il suo quanto o viene prelazionato da uno più importante. I thread real-time possono prelazionare gli altri. 32 livelli di priorità: classe variabile 1-15, real-time 16-31, priorità 0 per il thread di gestione della memoria; una coda per ogni priorità; se non c'è nessun thread pronto, gira il thread idle.

Esercizi collegati

Domande d'esame

1. Due compiti periodici hanno p1=30p_1=30, t1=10t_1=10, p2=40p_2=40, t2=20t_2=20. Sono schedulabili con RMS? E con EDF? Traccia. Utilizzo 10/30+20/40=0,333+0,5=0,833>0,82810/30 + 20/40 = 0{,}333 + 0{,}5 = 0{,}833 > 0{,}828: oltre il limite RMS per N=2N=2, ma il limite è solo una condizione sufficiente, quindi serve la verifica diretta. Con RMS P1P_1 ha la priorità: P1P_1 0-10, P2P_2 10-30, P1P_1 30-40, P2P_2 40-60, P1P_1 60-70, ... sull'iperperiodo 120 tutte le istanze finiscono entro la scadenza (la prima di P2P_2 a 30, la seconda a 60, la terza a 110): RMS funziona. Con EDF basta U≤1U \le 1: sì (qui la sequenza è identica).

2. Che differenza c'è tra push migration e pull migration? Perché il bilanciamento va contro l'affinità? Traccia. Push: un compito periodico sposta thread dai processori sovraccarichi agli altri; pull: un processore inattivo ne prende uno da uno occupato. Spostare un thread fa perdere il contenuto della cache del processore precedente, quindi riduce l'affinità.

3. Spiegare la differenza tra soft e hard real-time e il ruolo della latenza di dispatch. Traccia. Soft: priorità ai compiti critici, nessuna garanzia sulla scadenza. Hard: la scadenza deve essere rispettata, quindi il sistema deve fornire anche garanzie. La latenza di dispatch è il tempo per togliere un processo dalla CPU e far girare quello critico: deve essere piccola e limitata.

Versione ripasso

  • Latenza di evento = interrupt latency + dispatch latency. Soft real-time: priorità ai compiti critici, nessuna garanzia. Hard: scadenza obbligatoria.
  • Compito periodico: burst tt, scadenza dd, periodo pp, 0≤t≤d≤p0\le t\le d\le p; utilizzo t/pt/p; si somma. Controllo di ammissione.
  • Priorità sbagliata: (50,20) e (100,35) con P2P_2 prioritario: P1P_1 finisce a 55 > 50. Con Rate Monotonic (P1P_1 prioritario): P1P_1 0-20, P2P_2 20-50, P1P_1 50-70, P2P_2 70-75.
  • RMS: priorità fissa, periodo minore = priorità maggiore; ottimo tra le priorità fisse solo se U≤N(21/N−1)U\le N(2^{1/N}-1) (2 compiti: 82,8%; 3: 78,0%; →ln⁡2\to\ln2). Controesempio (50,25) e (80,35): U=0,9375U=0{,}9375, P2P_2 finisce a 85 > 80.
  • EDF: priorità dinamica, scadenza più vicina; garantisce le scadenze se U<100%U<100\%; prelazione solo con scadenza strettamente minore.
  • Ripartizione proporzionale: TT quote, N/TN/T del tempo; ammissione se restano quote.
  • SMP: coda comune o code private; CMT/hyperthreading (4 core x 2 = 8 processori logici), cambio di thread sullo stallo di memoria; scheduling a due livelli.
  • Bilanciamento: push (compito che sposta) e pull (processore inattivo tira); affinità soft/hard (cache calda); NUMA-aware (memoria vicina).
  • Linux: CFS -> EEVDF, domini di scheduling. Windows: 32 livelli (1-15 variabile, 16-31 real-time, 0 gestione memoria), una coda per priorità, thread idle. Rimandi: InterruptClassi di interruzioni; I/O guidato da interrupt; sequenza hardware e software di gestione con salvataggio del contesto sullo stack; identificazione della sorgente (linee multiple, polling, daisy chain, vettore); priorità e interruzioni annidate; eccezioni e modi in ARM.Interrupt →, Memoria cacheBlocchi, linee ed etichette; scomposizione dell'indirizzo; associazione diretta, completamente associativa e associativa a insiemi con calcolo dei campi; politiche di rimpiazzo (LRU, FIFO, casuale); politiche di scrittura (write-through, write-back con bit sporco, write-allocate); dimensione del blocco; cache multilivello e separate; come ridurre i miss; quesiti sui campi dell'indirizzo.Memoria cache →.
  • Latenze: di interrupt (arrivo dell'interrupt →\to inizio della routine) e di dispatch (togliere un processo dalla CPU e far partire il critico); devono essere piccole e limitate per un hard real-time.
  • Criterio RMS, due compiti: U≤2(2−1)=0,828U\le 2(\sqrt2-1)=0{,}828 garantisce; oltre il limite serve la verifica diretta. Verifica diretta = simulare sull'iperperiodo (mcm dei periodi): controllare ogni istanza.
  • EDF, regola di prelazione: la scadenza assoluta del nuovo arrivo deve essere strettamente minore di quella del processo in esecuzione. Valido anche per compiti non periodici.
  • Quote proporzionali: esempio T=100T=100, A=50A=50, B=15B=15, C=20C=20: 50%, 15%, 20%; un DD con 30 quote non entra (restano 15).
  • Multicore e hyperthreading: 4 core ×\times 2 thread hardware = 8 processori logici; durante uno stallo di memoria il core passa a un altro thread hardware; due livelli: il SO sceglie il thread software, il core sceglie il thread hardware.
  • Code in SMP: coda comune (serve sincronizzazione) o code private (richiedono bilanciamento). Push migration = un compito sposta i thread dai processori sovraccarichi; pull migration = un processore inattivo ne tira uno. Il bilanciamento contrasta l'affinità (cache calda persa). Soft (si cerca) / hard (insieme di processori specificato).
  • Linux: CFS →\to EEVDF, domini di scheduling (core che condividono cache), NUMA-aware. Windows: 32 livelli (1-15 variabile, 16-31 real-time, 0 per la memoria), una coda per priorità, idle se nulla è pronto.
  • Errori tipici: credere che U<100%U<100\% basti anche per RMS; usare il periodo sbagliato per la priorità; dimenticare le istanze successive nella verifica; calcolare i processori logici senza moltiplicare i thread per core.

Esercizi su questo argomento

Teoria collegata