POSSIBILI PROVE: 1. La memoria virtuale. 2. Classificazione di Flynn per le architetture parallele 3. Critiche al parallelismo: La legge di Amdhal 4. Unità di controllo micro programmate 5. Architetture RISC. Ragioni per la loro introduzione ed esempi. 6. Architetture superscalari. 7. Descrivere l’architettura di una CPU con organizzazione a pipeline. Illustrare con un esempio le funzioni svolte dai singoli stadi 8. Tecniche di accesso ai dati in una memoria cache. Illustrare le ragioni per le quali questo tipo di accesso è critico e come la tecnica set-associative per l’accesso ai dati di una cache risolva i problemi. Spiegare la necessità di utilizzare arbitri per la gestione di interruzioni multiple. Illustrare un esempio di soluzione. a. Descrivere i meccanismi di gestione delle interruzioni. Come vengono gestite le interruzioni che si presentano “contemporaneamente” alla CPU ? Come viene gestito l’annidamento delle interruzioni ? b. Tecniche per la gestione di interruzioni multiple. Accesso diretto alla memoria. Illustrare l’architettura del modulo e i vantaggi di questa soluzione Sistemi a bus. Protocolli per il trasferimento dei dati e le operazioni di lettura e scrittura. Gestione di I/O a controllo di programma cluster i sistemi di memoria Arbitri: spiegare le funzioni svolte e i possibili modi di implementazione (concentrato-distribuito). 9. 10. 11. 12. 13. 14. 15. 16. Le politiche di sostituzione in una struttura di memoria gerarchica. (Fifo lru) 1 1 Memoria virtuale 2 Tassonomia di Flynn In informatica, la memoria virtuale è una architettura di sistema capace di simulare uno spazio di memoria centrale maggiore di quello fisicamente presente; questo risultato si raggiunge utilizzando spazio di memoria secondaria su altri dispositivi, di solito le unità a disco. La memoria centrale fisicamente presente diventa quindi la parte effettivamente utilizzata di quella virtuale, più grande: questo stratagemma è utile in virtù del principio di località Memoria paginata Con questo schema la memoria viene divisa in pagine tutte della stessa grandezza (4 o 8 kilobyte): i programmi non hanno bisogno di sapere nulla su come è organizzata la memoria e non devono avere nessuna struttura interna particolare; la esatta ubicazione e disposizione fisica della memoria che occupano non li riguarda e tutto il sistema di memoria virtuale è completamente gestito dalla MMU attraverso un complesso sistema di registri associativi. Proprio questo sistema di registri è il punto debole di questo tipo di meccanismo: se il numero delle pagine è molto grande (pagine di piccole dimensioni, oppure grandi quantità di memoria virtuale da emulare) il meccanismo associativo può diventare troppo complesso, rallentando sensibilmente l'accesso alla memoria (e quindi tutto il sistema). Più dettagliatamente il meccanismo di gestione della memoria virtuale con paginazione è il seguente. L'immagine di un processo è suddivisa in pagine di dimensione fissa. La memoria principale (RAM) è suddivisa anch'essa in "pezzi", della stessa dimensione delle pagine, detti page frame. Ad ogni processo è associata una tabella, mantenuta in memoria principale o secondaria a seconda delle dimensioni, detta tabella delle pagine. Ogni entrata (riga) della tabella delle pagine contiene: Il numero di pagina per quella riga, Il bit present , Il bit modified, Il numero di frame corrispondente. Gli indirizzi logici sono rappresentati dalla coppia (nr. di pagina, offset). La traduzione avviene in questo modo: si trova la riga corrispondente al numero di pagina dell'indirizzo logico, se il bit Present è 0, la pagina non è presente in memoria principale, si genera quindi un Page Fault e si attende che la pagina sia caricata in memoria, infine si genera l'indirizzo fisico (nr. frame, offset). Il bit Modified indica invece se la pagina è stata modificata o meno. Infatti se una pagina non è stata modificata, al momento di effettuare lo swap nella memoria secondaria, non ha senso riscrivere la pagine su disco. Risparmiando così tempo, e migliorando in parte le prestazioni. Memoria segmentata In questo caso il meccanismo di memoria virtuale è in parte software: i programmi che girano su sistemi con memoria segmentata sono strutturati in segmenti funzionalmente omogenei: la MMU tiene traccia di quali e quanti segmenti sono presenti in memoria e dove. Il vantaggio principale di questo sistema è che sfrutta al massimo il già citato principio di località, riducendo al minimo il ricorso allo spazio di swap: una volta che un programma ha in memoria centrale i segmenti di cui necessita. principio di località. (Il principio di località enuncia che, se la CPU sta eseguendo una data istruzione, vuol dire che con molta probabilità le prossime istruzioni da eseguire saranno ubicate nelle vicinanze di quella in corso; vale a dire che, durante la normale esecuzione dei programmi, la CPU passa molto tempo accedendo a zone di memoria ristrette e solo occasionalmente accede a locazioni molto lontane. Inoltre, in genere gran parte del codice di cui sono costituiti i programmi viene eseguito solo raramente, al verificarsi di errori o condizioni anomale: quindi succede spesso che di tutto il codice che un programma carica in memoria ne venga realmente eseguita solo una piccola parte. classifica le architetture dei calcolatori 4 termini principali si ottiene la suddivisione principale: single, multiple, instruction, data SISD: unico calcolatore con un unico processoreArchitettura tradizionale con singola CPU che elabora unaistruzione alla volta operando su un dato alla volta. SIMD: stessa istruzione su più dati in parallelo. Gli array processor hanno un ALU comandate da un’unica unità di controllo. Tutte le unità eseguono la stesse istruzione ma su dati differenti. E’ necessaria un’unica copia del programma da eseguire. I vector processor hanno unità funzionali con pipeline che operano su pochi elementi per ogni colpo di clock. Più CPU operano in modo sincrono eseguendo la stessa istruzione su dati diversi. MIMD: più istruzioni su più dati. Si suddividono in due categorie: Il medesimo flusso di dati viene elaborato da un insiemedi processori che eseguono istruzioni diverse. classificazione di enslow� Questa classificazione vuole individuare lecaratteristiche che deve avere una architettura per dirsi distribuita� La classificazione di Enslow colloca learchitetture in uno spazio tridimensionaleUn sistema è completamente distribuito selo è nelle tre dimensioni Classificazione di Enslow Enslow nel 1980 ha proposto di collocare le architetture dei sistemi di elaborazione in uno spazio tridimensionale le cui dimensioni sono: Elaborazione – Dati – Controllo Unità di elaborazione singola. Unità di elaborazione singola ma con più unità funzionali. Unità di elaborazione multiple omogenee o eterogenee. Base di dati centralizzata. Base di dati distribuita fisicamente con direttorio centralizzato. Base di dati distribuita fisicamente senza direttorio centralizzato. Punto di controllo unico. Relazioni di tipo master-slave statiche o dinamiche. Punti di controllo autonomi e/o cooperanti. Tra i due casi estremi (PC e Internet) si possono collocare tutte le architetture di elaborazione esistenti. SISD Singolo flusso di Istruzioni/Singolo flusso di Dati: convenzionalmente sono macchine con una singola CPU capace solamente di effettuare operazioni aritmetiche fra scalari. Si tratta dunque di un’architettura tradizionale con singola CPU che elabora un’istruzione alla volta operando su un dato alla volta. SISD è anche sinonimo di computer sequenziale. SIMD Singolo flusso di Istruzioni/Flusso di Dati multiplo: questo tipo di architettura include tutti i computer paralleli recenti come ILLIAC IV che hanno una singola unità di controllo del programma e molte unità indipendenti per l’esecuzione. In tale architettura più CPU operano in modo sincrono eseguendo la stessa istruzione su dati diversi. MISD Flusso di Istruzioni multiplo/Singolo flusso di Dati: pochi computer paralleli rientrano in questa classe. Computer con capacità di fault-tolerance hanno diverse CPU che processano gli stessi dati usando programmi differenti. Dunque il medesimo flusso di dati viene elaborato da un insieme di processori che eseguono istruzioni diverse. Secondo la classificazione di Enslow all’interno di un sistema ciò che è distribuito si identificacon: Elaborazione, Dati, Controllo. Questa classificazione vuole individuare le caratteristiche che deve avere un architettura per dirsi distribuita. Le architetture vengono collocate in uno spazio tridimensionale (ogni asse corrisponde ai tre elementi per identificare un sistema distribuito) in cui un sistema è completamente distribuito se lo è nelle tre dimensioni. Vediamo ora i singoli elementi evidenziando per ognuno in senso crescente la distribuzione: • Distribuzione dell’elaborazione: elaborazioni multiple omogenee o eterogenee. ibuita fisicamente con direttorio -slave statiche o mi e/o cooperanti. Gli estremi di un sistema classificato secondo Enslow sono il Personal Computer (con assenza di distribuzione) e INTERNET che rappresenta la struttura distribuita più completa. All’interno di questi due casi estremi si possono collocare tutte le architetture di elaborazione esistenti. 2 3 Legge di Amdahl La legge di Amdahl, che ha preso il nome del progettista di computer Gene Amdahl, viene usata per trovare il miglioramento atteso massimo in una architettura di calcolatori o in un sistema informatico quando vengono migliorate solo alcune parti del sistema. Nella sua forma più generale può essere espressa come: "Il miglioramento che si può ottenere su una certa parte del sistema è limitato dalla frazione di tempo in cui tale attività ha luogo" che può essere ulteriormente semplificata nella pratica regoletta: rendi veloce il caso piu frequente La legge di Amdahl viene usata spesso nell'informatica parallela per predire l'aumento massimo teorico di velocità che si ottiene usando più processori. Nell'ambito dei sistemi software la legge di Amdahl può essere interpretata in modo più tecnico, ma in parole povere significa che è l'algoritmo a decidere l'aumento di velocità, non il numero di processori. Prima o poi si raggiunge un punto in cui non si può parallelizzare ulteriormente l'algoritmo. Più tecnicamente, la legge riguarda l'aumento di velocità ottenibile da un miglioramento a un calcolo che influisce per una proporzione P di quel calcolo, dove il miglioramento riduce il tempo di calcolo di un fattore S. (Per esempio, se un miglioramento può velocizzare il 30% del calcolo, P sarà 0.3; se il miglioramento raddoppia la velocità della porzione modificata, S sarà 2.) La legge di Amdahl afferma che l'aumento di velocità complessivo prodotto dal miglioramento sarà 1/((1-P)+P/s) Parallelismo Nel caso speciale del parallelismo, la legge di Amdahl afferma che se F è la frazione di un calcolo che è sequenziale (cioè che non può beneficiare dal parallelismo), e (1 − F) è la frazione che può essere parallelizzata, allora l'aumento massimo di velocità che si può ottenere usando N processori è: 1/((F+(1-F))/N 4 Unità di controllo microprogrammate L'architettura dei calcolatori: microprogrammazione. I processori a logica programmata differiscono da quelli a logica dedicata soprattutto nell'unità di governo, in quanto ora essa stessa è il risultato di esecuzione di un microprogramma: al suo interno ci sono delle microunità che eseguono le operazioni elementari dei microprogrammi associati alle istruzioni macchina riconosciute dalla CPU . Realizzare un processore con questa tecnologia è più facile, soprattuto nel caso si desideri espandere il suo set di istruzioni. Nel precedente approccio a logica dedicata, era necessario realizzare una nuova rete logica per ciascuna nuova istruzione, poi si procedeva alla sua integrazione con il circuito preesistente. I microprogrammi sono memorizzati in un'area di memoria non cancellabile, ovvero di tipo ROM , che viene detta Memoria di Controllo. Ad ogni nuova revisione della CPU è sufficiente estendere questa memoria per ospitare i nuovi microprogrammi i quali sono scritti in un particolare linguaggio detto RTL . Possiamo riassumere il discorso dicendo che la CPU a logica microprogrammata possiede un proprio linguaggio a bassissimo livello attraverso il quale viene emulato il linguaggio macchina. Può sembrare una cosa strana, ma torna utile in più di un'occasione. Per esempio una macchina C1 con un linguaggio L1, può eseguire i programmi scritti nel linguaggio L2 per la macchina C2, semplicemente aggiungendo nella memoria di controllo della C1 i microprogrammi necessari per interpretare il linguaggio L2. In questi casi si dice che C1 può emulare C2. In teoria sarebbe possibile realizzare una CPU virtualmente compatibile con tutte le altre passate, presenti e future. La sua memoria di controllo non dovrebbe essere del tipo ROM, ma del tipo non volatile, ovvero una memoria che può essere alterata come la comunissima RAM , ma che non perda il suo contenuto quando l'alimentazione è interrotta. In questo modo, anche dopo la sua vendita sarà possibile estenderne le funzionalità, un po' come già accade oggi con gli aggiornamenti del BIOS delle piastre madri delle architetture WINTEL . . CRITICHE AL PARALLELISMO I supercomputer odierni sono una generazione indietro rispetto alle esigenze e una avanti rispetto all'abilità dei programmatori. • I problemi sono espressi in termini sequenziali. • Esiste una quantità "enorme" di programmi già sviluppati, sarebbe conveniente eseguirli più velocemente. • Legge di AMDAHL. RAGIONI NON TECNICHE L'introduzione e l’utilizzo efficace di sistemi di calcolo paralleli per ottenere prestazioni superiori a quelle delle architetture sequenziali presenta difficoltà che non sono solamente di carattere tecnico. La presenza di molti programmi già sviluppati per architetture sequenziali, le conoscenze dei programmatori e la loro abitudine a sviluppare programmi su architetture sequenziali rappresentano un investimento che non può essere trascurato. Inoltre lo sfruttamento efficace di tutte le caratteristiche delle architetture parallele richiede conoscenze che chi sviluppa le applicazioni spesso non ha. Effetti di operazioni sequenziali su di un sistema di elaborazione parallelo. • P: Numero di processori • T(P): tempo di esecuzione di un programma a parallelismo P. • f: frazione di programma che deve essere eseguita sequenzialmente. Tempo di esecuzione del programma su di una architettura a parallelismo P: LEGGE DI AMDAHL T(P) = f T(1) + (1-f) [T(1)/P] Speed Up: S(P) =T(1)/T(P) = 1/ [f + (1-f)/P] =P/[1 + f(P- 1)]. Efficienza: E(P) = S(P)/P = 1/[1 + f(P- 1)]. CONSEGUENZE • Una piccola porzione di codice non parallelizzabile può avere un grande effetto globale. • Riuscire a parallelizzare una porzione di codice sequenziale consente di migliorare significativamente le prestazioni. 3 5 Architetture CISC e architetture RISC Quando i transistor disponibili su un solo chip erano pochi e i calcolatori venivano spesso programmati in assembly, era naturale sfruttarli in modo tale da avere CPU con istruzioni potenti, evolute e complesse: più queste erano vicine alle istruzioni dei linguaggi di programmazione ad alto livello più il computer sarebbe stato facile da programmare, e i programmi avrebbero occupato poco spazio in memoria (anch'essa poca e preziosa). Le CPU progettate secondo questo approccio sono dette CISC ed avevano unità di controllo complesse capaci di sfruttare al meglio pochi registri e i cui programmi erano di dimensioni relativamente piccole. CISC è l'acronimo di Complex Instruction Set Computer: tipicamente un processore di questo tipo implementa un numero relativamente scarso (una decina) di registri di uso generale, ed ha una unità di controllo microprogrammata: la logica del programma è memorizzata in una memoria veloce situata nella parte di controllo, invece di essere espressa tramite una rete combinatoria. RISC (Reduced Instruction Set Computer) RISC è l'acronimo di Reduced Instruction Set Computer. Il tipico set di istruzioni RISC è molto piccolo, circa sessanta o settanta istruzioni molto elementari (logiche, aritmetiche e istruzioni di trasferimento memoria-registro e registro-registro): hanno tutte lo stesso formato e la stessa lunghezza, e molte vengono eseguite in un solo ciclo di clock. La diretta conseguenza di tale scelta progettuale è che i processori RISC posseggono una unità di controllo semplice e a bassa latenza, riservando invece molto spazio per i registri interni: una CPU RISC ha di solito da un minimo di un centinaio ad alcune migliaia di registri interni generici, organizzati in un file di registri. Il fatto di avere un formato unico di istruzione permette di strutturare l'unità di controllo come una pipeline, cioè una catena di montaggio a più stadi: questa innovazione ha il grosso vantaggio di ridurre il critical path interno alla CPU e consente ai RISC di raggiungere frequenze di clock più alte rispetto agli analoghi CISC. Nel caso di context-switch o di chiamata a subroutine o comunque di uso dello stack i RISC spesso invece di accedere alla memoria di sistema usano un meccanismo chiamato register renaming, che consiste nel rinominare i registri in modo da usare per la nuova esecuzione una diversa zona del file di registri, senza dover accedere alla memoria ogni volta. RISC vs CISC La semplicità dei RISC si traduce in una minore espressività del linguaggio assembler: il numero di word necessarie per esprimere una computazione in una macchina RISC è maggiore/uguale alla controparte CISC: questo si traduce in programmi più grossi, penalità molto alta in altre epoche, in cui la RAM era una componente costosa e di bassa capacità. L'architettura CISC dipende dal compilatore più di quanto non dipenda il RISC: dato che le istruzioni prevedono più metodi di indirizzamento, e che son presenti istruzioni dalla semantica complessa, al compilatore viene prospettato un'ampio ventaglio di scelte per quanto concerne la traduzione di una istruzione, e non sempre la scelta migliore è banale. Come spesso accade nei problemi di ottimizzazione, la scelta della configurazione migliore è un compito NP completo, e non è pensabile utilizzare un compilatore che, per ogni istruzione, valuti la scelta migliore in base al contesto. Si conoscono solo delle buone euristiche, ma il problema dell'ottimizzazione è un problema di ricerca aperto. La stessa macchina CISC può essere dunque più o meno veloce rispetto ad una macchina comparabile RISC in base al compilatore utilizzato. La vera differenza tra RISC e CISC è la filosofia di funzionamento. In una macchina RISC le uniche operazioni in grado di accedere alla memoria sono le operazioni di load e di store, tutte le altre utilizzano solo i registri, mentre in una macchina CISC le operazioni possono accedere ai registri e alla memoria indifferentemente. Questo non è possibile direttamente, quindi una macchina CISC quando un'operazione richiede di accedere alla memoria il processore carica il dato lo salva temporaneamente in un registro (spesso nascosto) esegue le operazioni e poi salva il risultato in memoria. In sostanza: una macchina CISC mette in piedi un teatro illusorio per fornire al programmatore un ambiente comodo; una macchina RISC non fornisce questo teatro illusorio al programmatore dato che questo comunque non programma quasi mai in assembly e dato che queste operazioni nascoste in realtà rallentano il processore nell'eseguire le altre operazioni. 6 Architetture superscalari. Un microprocessore con architettura superscalare supporta il calcolo parallelo su un singolo chip, permettendo prestazioni molto superiori a parità di clock rispetto ad una CPU ordinaria. Questa caratteristica è posseduta più o meno da tutte le CPU general purpose prodotte dal 1998. I microprocessori più semplici sono scalari: compiono una operazione sul numero di operandi di questa alla volta. Invece, in un processore vettoriale, una singola istruzione viene applicata su di un vettore, formato da più dati raggruppati. In questo modo, una applicazione che deve eseguire una certa operazione su una grande quantità di dati viene svolta con molta più rapidità. Un processore superscalare è una forma intermedia tra i due: istruzioni diverse trattano i propri operandi contemporaneamente, su diverse unità hardware all'interno dello stesso chip. In questo modo più istruzioni possono essere eseguite nello stesso ciclo di clock. Il semplice fatto di eseguire più istruzioni nello stesso ciclo di clock non rende una CPU superscalare: una CPU con una pipeline semplice, che può quindi caricare un'istruzione, eseguirne un'altra e immagazzinare il risultato di quella ancora precedente non è necessariamente superscalare. In una CPU superscalare sono presenti diverse unità funzionali dello stesso tipo, con dispositivi addizionali per distribuire le istruzioni alle varie unità. Per esempio, sono generalmente presenti numerose unità per il calcolo intero (definite ALU). Le unità di controllo stabiliscono quali istruzioni possono essere eseguite in parallelo e le inviano alle rispettive unità. Questo compito non è facile, dato che un'istruzione può richiedere il risultato della precedente come proprio operando, oppure può dover impiegare il dato conservato in un registro usato anche dall'altra istruzione; il risultato può quindi cambiare secondo l'ordine d'esecuzione delle istruzioni. La maggior parte delle CPU moderne dedica molta potenza per svolgere questo compito con la massima precisione possibile, per permettere al processore di funzionare a pieno regime in modo costante; compito che si è reso sempre più importante con l'aumento del numero delle unità. Mentre le prime CPU superscalari possedevano due ALU ed una FPU, un processore attuale come ad esempio il PowerPC 970 possiede quattro ALU, due FPU e due unità SIMD. Se il sistema di distribuzione delle istruzioni non mantiene occupate tutte le unità funzionali del processore, le sue prestazioni ne soffrono grandemente. Le architetture superscalari ebbero origine nell'ambiente RISC, dato che questo tipo di design richiede unità funzionali semplici, che possono essere incluse in più esemplari in una unica CPU. Questa è la ragione per cui questi processori erano più veloci dei CISC tra gli anni '80 e gli anni '90. Tuttavia, col progresso della tecnologia, anche design ingombranti come l'IA-32 poterono essere progettati in modo superscalare. Attualmente è impensabile un futuro miglioramento sensibile del sistema di controllo, ponendo di fatto un limite ai miglioramenti prestazionali dei processori superscalari. 4 7 Descrivere l’architettura di una CPU con organizzazione a pipeline. Illustrare con un esempio le funzioni svolte dai singoli stadi Pipeline dati Esecuzione delle istruzioni in un microprocessore senza pipeline IF-ID-EX-MEM-WB La pipeline dati è una tecnologia utilizzata dai microprocessori per incrementare il throughput, ovvero la quantità di istruzioni eseguite in una data quantità di tempo. L'elaborazione di un istruzione da parte di un processore si compone di cinque passaggi fondamentali: IF: Lettura dell'istruzione da memoria ID: Decodifica istruzione e lettura operandi da registri EX: Esecuzione dell'istruzione MEM: Attivazione della memoria (solo per certe istruzioni) WB: Scrittura del risultato nel registro opportuno Praticamente ogni CPU in commercio è gestita da un clock centrale e ogni operazione elementare richiede almeno un ciclo di clock per poter essere eseguita. Le prime CPU erano formate da un'unità polifunzionale che svolgeva in rigida sequenza tutti e cinque i passaggi legati all'elaborazione delle istruzioni. Una CPU classica richiede quindi almeno cinque cicli di clock per eseguire una singola istruzione. . La pipeline dati è la massima parallelizzazione del lavoro di un microprocessore. Esecuzione delle istruzioni in un microprocessore con pipeline Una CPU con pipeline è composta da cinque stadi specializzati, capaci di eseguire ciascuno una operazione elementare Problematiche L'implementazione di una pipeline non sempre moltiplica il throughput. L'analisi delle problematiche legate alla gestione delle pipeline per ottenere le migliori prestazioni teoriche ricadono sotto la ricerca del instruction level parallelism, il parallelismo a livello d'istruzione, cioè le istruzioni che possono essere eseguite in parallelo senza creare conflitti o errori di esecuzione. Comunque le singole pipeline affrontano due problemi principalmente; il problema legato alla presenza di istruzioni che possono richiedere l'elaborazione di dati non ancora disponibili e il problema legato alla presenza di salti condizionati. Il primo problema deriva dal lavoro parallelo delle unità. e quindi la seconda operazione dovrà bloccarsi per attendere il completamento della prima e quindi questo ridurrà il throughput complessivo. Il secondo problema consiste nei salti condizionati. I programmi contengono delle istruzioni condizionate che se una specifica condizione è verificata provvedono a interrompere il flusso abituale del programma e a mandare in esecuzione un altro pezzo di programma indicato dall'istruzione di salto. Ogni volta che questo accade il microprocessore si trova a dover eseguire un nuovo flusso di operazioni e quindi deve svuotare la pipeline del precedente flusso e caricare il nuovo flusso. Ovviamente queste operazioni fanno sprecare cicli di clock e quindi deprimono il throughput. Per ridurre questo problema le CPU adottano delle unità chiamate unità di predizione delle diramazioni (in inglese Branch Prediction Unit) che fanno delle previsioni sul flusso del programma. Queste unità riducono notevolmente i cicli persi per i salti. 8 Tecniche di accesso ai dati in una memoria cache. Illustrare le ragioni per le quali questo tipo di accesso è critico e come la tecnica set-associative per l’accesso ai dati di una cache risolva i problemi. MEMORIA ASSOCIATIVA Memoria tradizionale: (in lettura)restituisce un dato conoscendone la posizione (indirizzo). Memoria associativa: restituisce unainformazione associata fornendo un dato TECNICHE ASSOCIATIVE� Il tag viene utilizzato come chiave dilettura� La cache è organizzata come una memoria associativa Come si è già visto in precedenza la tecnica associativa è molto costosa quando le dimensioni della memoria crescono La CPU cache è la cache utilizzata dalla CPU di un computer per ridurre il tempo medio d'accesso alla memoria. La cache è un tipo di memoria piccola, ma molto veloce, che mantiene copie dei dati ai quali si fa più frequentemente accesso in memoria principale. Finché la maggior parte degli accessi alla memoria avviene su dati caricati nella cache, la latenza media dell'accesso alla memoria sarà più vicina alla latenza della cache piuttosto che a quella della memoria principale.. Ogni locazione di memoria ha anche un indice, cioè un identificatore univoco utilizzato per riferirsi a quella specifica locazione. L'indice di una locazione in memoria principale è chiamato indirizzo di memoria. Ogni locazione nella cache ha un'etichetta che contiene l'indice in memoria principale del dato ivi caricato. Nelle cache dati, questi valori sono chiamati blocchi di cache o linee di cache. Quando il processore vuole leggere o scrivere in una data locazione in memoria principale, inizialmente controlla se il contenuto di questa locazione è caricato in cache. Questa operazione viene effettuata confrontando l'indirizzo della locazione di memoria con tutte le etichette nella cache che potrebbero contenere quell'indirizzo. Se il processore trova che la locazione di memoria è in cache, si parla di cache hit (accesso avvenuto con successo), altrimenti di cache miss (fallimento d'accesso). Nel caso di un cache hit, il processore legge o scrive immediatamente il dato sulla linea di cache. Il rapporto tra cache hit e accessi totali è chiamato anche hit rate ed è una misura dell'efficacia della cache stessa.Nel caso di un cache miss, la maggior parte delle cache crea una nuova entità, che comprende l'etichetta appena richiesta dal processore ed una copia del dato dalla memoria. Un fallimento del genere è relativamente lento, in quanto richiede il trasferimento del dato dalla memoria principale, il cui tempo di risposta è molto maggiore di quello della memoria cache.Alcuni dettagli operativi Per poter fare spazio a nuovi dati nel caso di un cache miss, la cache generalmente deve eliminare il contenuto di una delle linee. L'euristica che utilizza per scegliere quale dato eliminare è chiamata politica di rimpiazzamento. Il problema fondamentale di ogni politica di rimpiazzamento è quello di dover predire il dato della cache che verrà richiesto nel futuro con minor probabilità. Predire il futuro è difficile, soprattutto per le cache hardware che devono sfruttare regole facilmente implementabili in circuiteria, perciò esistono una serie di politiche di rimpiazzamento e nessuna di esse può essere ritenuta perfetta. Una delle più popolari, la LRU (dall'inglese Least Recently Used, cioè usato meno recentemente), rimpiazza, appunto, il dato al quale si è fatto accesso meno recentemente. Associatività Quali locazioni di memoria possono essere caricate in quali locazioni della cache La politica di rimpiazzamento decide dove, nella cache, può risiedere una copia di una particolare locazione di memoria. Se la politica di rimpiazzamento è libera di scegliere in quale linea di cache caricare il dato, la cache è chiamata fully associative (o anche completamente associativa). Invece, se ogni dato in memoria può essere posizionato solo in una particolare linea di cache, essa è detta direct mapped (o anche a mappatura diretta). La maggior parte delle cache, però, implementa un compromesso chiamato set associative (o anche parzialmente associativa). Per esempio, la cache dati di livello 1 dell'AMD Athlon è 2-way set associative, cioè una particolare locazione di memoria può essere caricata in cache in due distinte locazioni nella cache dati di livello 1.Se ogni locazione in memoria principale può essere caricata in due locazioni diverse, la domanda sorge spontanea: quali? Lo schema utilizzato più frequentemente è mostrato nel diagramma a lato: i bit meno significativi dell'indice della locazione di memoria vengono usati come indici per la cache e ad ognuno di questi indici sono associate due linee di cache. Una buona proprietà di questo schema è che le etichette dei dati caricati in cache non devono includere quella parte dell'indice già codificata dalla linea di cache scelta. Poiché i tag sono espressi su meno bit, occupano meno memoria ed il tempo per processarli è minore. determinare quale tra le linee esistenti è stata usata meno recentemente, in quanto la nuova linea entra in conflitto con differenti "set" di linee per ogni "way"; il tracciamento LRU è infatti normalmente calcolato per ogni set di linee. L'associatività è un compromesso. Se ci sono dieci posizioni, la politica di rimpiazzamento può riempire una nuova linea, ma quando bisogna cercare un dato devono essere controllate tutte e 10 le posizioni. Controllare più posizioni necessita di più potenza, area e tempo. D'altra parte, le cache con più associatività soffrono di meno cache miss (vedere anche più in basso). La regola di massima è che raddoppiare l'associatività ha circa lo stesso effetto sull'hit rate che il raddoppio della dimensione della cache, da 1-way (direct mapping) a 4-way. Aumenti dell'associatività oltre il 4-way hanno molto meno effetto sull'hit rate e sono generalmente utilizzati per altri motivi (vedere il virtual aliasing, più in basso). 5 9 Spiegare la necessità di utilizzare arbitri per la gestione di interruzioni multiple. Illustrare un esempio di soluzione. a. b. Descrivere i meccanismi di gestione delle interruzioni. Come vengono gestite le interruzioni che si presentano “contemporaneamente” alla CPU ? Come viene gestito l’annidamento delle interruzioni ? Tecniche per la gestione di interruzioni multiple. La gestione di interruzioni multiple avviene utilizzando il meccanismo di annidamento immagazzinando nello stack gli indirizzi di ritorno e i relativi contesti. Si possono verificare problemi se è in fase di esecuzione una attività con caratteristiche stringenti di tempi di servizio e se l’interruzione di tale unità non è possibile. Pertanto è necessario un meccanismo che impedisca le interruzioni quando non sono opportune: in particolare tutte le richieste di interruzione vengono ignorate, ad ogni richiesta è associata una urgenza (o priorità) e alla CPU giunge la sola richiesta a priorità maggiore. La CPU può anche decidere di accettare solo (in ogni istante) le richieste di interruzione con urgenza (o priorità) superiore ad un dato livello. In generale più periferici possono richiedere interruzione. La gestione delle interruzioni può anche essere di tipo centralizzato ovvero tutte le richieste sono gestite da un solo modulo che emette un vettore (codice) corrispondente alla richiesta d’interruzione che il modulo di controllo ritiene a priorità maggiore. Tale vettore è specifico per ogni periferica che può richiedere l’interruzione. E’ come se la CPU costruisse un’istruzione di call di cui l’hardware gli passa parte dell’indirizzo. In un sistema modulare a bus non è possibile utilizzare molte linee dedicate. Nel caso di gestione distribuita la selezione del periferico avviene con polling e vettorizzazione. Nel caso del polling ogni elemento periferico dispone di un registro che contiene un bit che segnala la richiesta di interruzione e una sola routine di gestione legge in sequenza tutti i registri. Nel caso della vettorizzazione ogni periferico invia alla CPU un valore o vettore identificatore. Il vettore viene utilizzato per individuare il programma opportuno di gestione dell’interruzione.Se più periferici chiedono contemporaneamente interruzione, occorre stabilire chi servire per primo applicando regole di arbitrazione che possono essere di tipo concentrato o distribuito.. La gestione di interruzioni multiple avviene utilizzando il meccanismo di annidamento immagazzinando nello stack gli indirizzi di ritorno e i relativi contesti. NTERRUPT • Evento infrequente ed eccezionale. • Generato internamente o esternamente. • Causa il trasferimento del controllo a un programma specifico di servizio dell'evento. L’interruzione è utilizzata per la gestione degli apparatidi I/O. Per ottenere risposte rapide nella gestione didischi, tastiere (keyboard), modem, ... Questi elementi devono richiamare l'attenzione della CPU molto rapidamente e il trasferimento dei dati da e verso gli questi organi deve avvenire nel modo più efficiente possibile. E’ necessario assegnare urgenze o priorità diverse alle varie richieste di intervento se contemporanee. INTERRUPT ESTERNI Gestione di I/O mediante interrupts: • La CPU non deve verificare con continuità lo stato dei dispositivi di I/O. • Accesso diretto e rapido alla CPU per: • richiesta inizio operazione. • segnalazione di fine operazione. INTERRUPT INTERNI Provenienti dall'interno della CPU in condizioni particolari (traps): • errori (divisione per 0, overflow). • malfunzionamenti hardware (errori di trasferimento dati sul bus). GESTIONE INTERRUPT • La presenza di un interrupt è segnalata alla CPU da una linea proveniente dall'esterno • Il segnale viene memorizzato è testato dalla CPU alla fine di ogni ciclo di istruzione • La CPU risponde trasferendo il controllo a un altro programma • A cura della CPU (polling). • A cura dell'elemento che genera interruzione. • La CPU ottiene l'indirizzo di memoria del programma di servizio: • Al termine della fase di polling. • Durante la stessa richiesta di interruzione. • Il PC e altre informazioni essenziali (contesto) relative alla CPU vengono memorizzate automaticamente. INTERRUZIONI MULTIPLE • La gestione di interruzioni multiple avviene utilizzando il meccanismo di annidamento. • Gli indirizzi di ritorno e i relativi contesti possono essere immagazzinati nello stack. 10 Accesso diretto alla memoria. Illustrare l’architettura del modulo e i vantaggi di questa soluzione. Accesso Diretto alla Memoria (DMA) Si è visto nelle sezioni precedenti come sia necessario sincronizzare l'accesso della CPU ai dispositivi esterni (periferiche). In particolare si sono analizzate le due tecniche di polling e di interrupt, e si è visto come la seconda tecnica consenta un utilizzo più efficiente della CPU specialmente quando il dispositivo è significativamente più lento della CPU. Se il dispositivo è più veloce, la tecnica ad interrupt pone dei limiti alla velocità di trasferimento dei dati. Una terza metodologia consente il trasferimento dei dati tra la periferica e la memoria senza il coinvolgimento diretto della CPU, se non per l'inizializzazione e la terminazione del trasferimento. Tale tecnica prende il nome di Direct Memory Access (DMA). La gestione del DMA richiede un modulo di controllo esterno alla CPU (anche se spesso montato a bordo dello stesso chip), collegato alla periferica ed al bus di comunicazione. Tale dispositivo, detto DMA controller, consente l'impostazione tramite un insieme di registri di configurazione visibili dalla CPU. Di questi registri, sono comuni a tutti di DMA controllers il registro CAR (Current Address Register) ed il egistro WC (Word Count). Per impostare un trasferimento DMA la CPU provvede ad inizializzare tali registri: il registro CAR viene impostato all'indirizzo iniziale in memoria del blocco di dati da essere trasferito (sequenziale in memoria) , ed il registro WC al numero di elementi da trasferire. Una volta iniziato il trasferimento DMA (normalmente tramite la scrittura di un apposito codice nel Command Register del DMA controller), il controllore DMA provvederà autonomamente al trasferimento dei dati da o per la memoria, non appena la periferica collegata (ed opportunamente programmata dalla CPU) sia disponibile. Si osservi che la periferica risulterà collegata al DMA controller per lo scambio dei dati, ma anche al bus di comunicazione per la programmazione da parte della CPU (tipicamente attraverso un insieme di registri visti come locazioni di memoria in un'architettura memory mapped). Quando il DMA controller è pronto a trasferire uno o più dati deve richiedere l'accesso al bus di comunicazione, normalmente utilizzato dalla CPU. L'arbitraggio del bus deve avvenire in maniera controllata per evitare conflitti tra CPU e DMA controller. Per questa ragione i bus di comunicazione normalmente prevedono un protocollo ed alcune linee di controllo per l'arbitrazione del bus. In ogni momento tra i dispositivi collegati al bus è definito un singolo Proprietario del bus (Bus Master). Normalmente il Bus master è la CPU, ma un altro dispositivo può richiedere di diventare il Bus Master. Questo è il caso del DMA controller quando questi deve trasferire uno o più dati. Il dispositivo richiedente segnalerà la richiesta al bus Master corrente tramite una linea di controllo (Bus Request), ed il Master corrente segnalerà la cessione del bus tramite un'altra linea di controllo (Bus Grant). A questo punto il DMA controller ha il possesso del bus e potrà utilizzare il bus per il trasferimento dei dati da o per la memoria, fino a che il bus non venga nuovamente richiesto dalla CPU o da un altro dispositivo. Ad ogni trasferimento, il DMA controller modificherà il registro CAR che ora punterà al successivo dato da trasferire in memoria, e decrementerà il registro WC. Quando il contenuto del registro WC diventa zero, tutti i dati impostati sono stati trasferiti. Quando non è il bus Master, la CPU può procedere con le operazioni interne che non richiedano un accesso al bus. Si noti che la presenza della cache consente alla CPU di procedere anche con operazioni di accesso alla memoria a patto che queste generino uno Hit nella cache. Al primo Miss, la CPU dovrà richiedere nuovamente l'accesso del Bus per il trasferimento dei dati con la memoria. Si osservi che durante un trasferimento DMA di un blocco di dati il bus può essere scambiato più volte tra la CPU ed il DMA controller. Tale meccanismo è tuttavia gestito completamente dall'hardware, e risulta quindi completamente trasparente al programma. L'impatto del trasferimento DMA sulla performance della CPU risulta limitato alle possibili contenzioni sul bus, ovvero alla possibile attesa richiesta alla CPU per riprendere possesso del bus. In un sistema opportunamente equilibrato, tale riduzione di performance risulta assai limitata, per cui il trasferimento DMA risulta quasi trasparente all'esecuzione normale della CPU. Poiché il trasferimento dei dati in DMA procede autonomamente dal flusso di esecuzione del programma, occorre un meccanismo per notificare la CPU dell'avvenuto trasferimento del blocco di dati. Tale notifica avviene tramite un opportuno interrupt generato dal DMA controller quando il trasferimento del blocco impostato è terminato. La routine di servizio associata intraprenderà le azioni necessarie per la notifica del trasferimento avvenuto. E' normalmente il sistema operativo che gestisce il trasferimento DMA per dispositivi quali i dischi magnetici o le schede di rete, ed in generale per tutti quei dispositivi caratterizzati da un'alta velocità di trasferimento. 6 12 Gestione I/O a controllo di programma 11 Sistemi a BUS Ingresso e Uscita Lo spostamento dei dati tra moduli e l’acquisizione di dati dall’esterno è uno degli aspetti più critici di un sistema di elaborazione influenzando in modo particolare prestazioni, costi, modularità e standardizzazione. Esistono diverse tipologie di trasferimento, di seguito analizzeremo le principali. • Trasferimento dati punto a punto. Abbiamo due attori del sistema che sono la sorgente e la destinazione. Il segnale di strobe comanda la memorizzazione del dato, la cui trasmissione avviene in modo diretto. Il trasferimento punto a punto richiede un solo segnale di strobe per segnalare all’elemento ricevente la presenza del dato corretto e dunque il fatto che va’ immagazzinato. Trasferimento a diffusione. Si definisce tale in quanto potenzialmente tutte le destinazioni possono vedere l’informazione trasmessa dalla sorgente in quanto sono tutte collegate ad uno stesso BUS. Tuttavia ogni destinazione è pilotata dal proprio segnale di strobe. In questo tipo di logica uno stesso elemento invia dati a più destinazioni. Trasferimento a collettore. Più elementi possono inviare dati a un destinatario. Non è possibile che più sorgenti trasmettano contemporaneamente altrimenti genererebbero conflitti si accesso sul BUS. Dunque, il canale di trasferimento viene utilizzato per un solo trasferimento per volta. In tale logica ogni sorgente avrà un segnale di output enable che regolerà la possibilità o meno di trasmettere. Arbitro centralizzato che fornisce la possibilità di modificare agevolmente la politica di assegnazione e che presenta maggior osservabilità ovvero si può facilmente sapere cosa sta succedendo in quanto tale informazione risiede in una sola fonte (l’arbitro appunto). La politica delle priorità è contenuta all’interno dell’allocatore che risponde sempre con una sola concessione. L’unità di controllo risponde con un solo grant in base alle priorità. All’interno dell’allocatore è definita la politica di assegnazione delle risorse. Vediamo dunque due possibili versioni dell’allocatore concentrato La differenza fra i due circuiti sta nel fatto che crescendo di numero di moduli che richiedono l’accesso, nel primo caso serviranno porte con sempre più ingressi, mentre nel secondo caso ci si limita ad allungare la catena. Nel primo caso ci sono i problemi di costo e complessità dovuti a porte con n ingressi, mentre nel secondo le problematiche risiedono nei tempi di propagazione che si allungano. Arbitro distribuito che fornisce maggiore modularità e possibilità di espansione e riconfigurazione e inoltre migliore tolleranza ai guasti. Il circuito dell’arbitro distribuito è uguale a quello concentrato, varia la distribuzione delle parti hardware. Se voglio variare la priorità posso sfruttare dei meccanismi ad anello anche se in realtà si tratta di una struttura prevalentemente fissa. o Esistono alcune tecniche di arbitrazione (a distribuzione decrescente): a catena o daisy-chain, polling, a richieste indipendenti. Il ciclo di acquisizione del controllo del bus è gestito da un arbitro e avviene con una sorta di meccanismo di handshake. Polling. In questo caso, in corrispondenza di una richiesta il modulo di controllo genera una sequenza di indirizzi corrispondenti alle varie unità. Il modulo indirizzato con una richiesta pendente assume il controllo. L’unità interroga in sequenza i vari moduli tramite la generazione di indirizzi. Il vantaggio è che la priorità non è più statica (fisica), ma è determinata dal modo in cui l’unità di controllo genera indirizzi, o meglio, l’ordine con cui li emette e che quindi è gestibile via software. Vediamo ora la struttura di una generica porta d’ingresso. Nella forma minima richiede solodei buffer. Il sistema in figura è in grado di gestire delle uscite a tre stati grazie alla regione difunzionamento in alta impedenza.Se pensiamo alla connessione contemporanea ad uno stesso DBUS di dispositivi come questo cirendiamo immediatamente conto che è vietato collegare le uscite in quel modo. Tuttavia grazie allagestione a tre stati è possibile avere tali tipi di configurazioni, questo perché sfruttando la zona di alta impedenza dei dispositivi si ha come una sorta di interruttore interno che viene aperto nel momento in cui il dispositivo deve essere abilitato; in questo modo solo un dispositivo sarà acceso contemporaneamente e questa risulta essere una configurazione lecita. Vediamo ora un semplice schema di porta d’uscita che nella sua forma minima richiede solo dei latch. All’interno dell’architettura di sistema avremo che le varie unità periferiche dialogheranno con la cpu attraverso delle opportune interfacce che trasmetteranno dati su dei bus (bus indirizzi e bus dati) e delle linee di controllo. I dispositivi procedono in modo asincrono rispetto alla CPU e dunque serve un’interfaccia che consenta il dialogo e che dunque dovrà fornire: un registro per i dati trasferiti, un registro per i co andi della periferica ed un registro per lo stato della periferica. L’interfaccia svolge dunque la funzione di adattamento sia elettrico sia logico tra le unità periferiche e il calcolatore. Ricordiamo che un registro è una locazione con un determinato indirizzo a cui la CPU può accedere in lettura e/o scrittura. Dunque ad ogni registro è associato un indirizzo il cui riconoscimento determina la selezione del relativo registro; si utilizza il termine porta. Vediamo dunque lo schema di un’interfaccia. In figura sono rappresentati il registro dati, quello di stato e quello di controllo; in particolare le frecce indicano la direzione del flusso informativo. Si osservi che solo il registro dati presenta un flusso bidirezionale Nella gestione a controllo di programma, vi è una sorta di routine che diventa una componente software che nasconde al suo interno la gestione della periferica. Si tratta di una specie di dispositivo che svolge una determinata funzione. Tuttavia con questo tipo di metodologia nessun altra attività viene svolta dal processore, se non quella di osservare lo stato della periferica; dunque il tempo di CPU è totalmente sprecato nell’attesa. Si pensi ad esempio ad una routine che gestisca un dispositivo di stampa in cui la CPU (ordine di 100M istr/s) attenda la stampa di ogni singolo carattere ovvero irca 10ms. Tra carattere e carattere la CPU avrebbe tempo per eseguire 10.000 istruzioni. Dunque con la gestione a controllo di programma si viaggia alla velocità del dispositivo periferico. Vediamo un semplice schema di interfaccia d’uscita. 7 13 CLUSTER Per cluster si intende una classe di architetture di elaborazione parallele basate su un insieme di elaboratori indipendenti, cooperante per mezzo di una rete di interconnessione e coordinato mediante un sistema operativo che lo rende in grado di operare su di un singolo workload. Il commodity cluster è costituito da nodi di elaborazione commerciali (COTS – Commercial off the shelf) in grado di operare in modo indipendente e collegati tramite una rete di interconnessione (LAN o SAN) anch’essa di tipo COTS. Un cluster può essere utilizzato in molti modi come ad esempio ottenere elevate prestazioni su di un singolo problema, elevato throughput o elevata capacità con un carico di lavoro a processi, elevata disponibilità mediante la ridondanza dei nodi, elevata banda ottenuta dalla molteplicità dei dischi o dei canali di I/O. Gli aspetti che giustificano l’interesse così forte per i sistemi a cluster sono sicuramente il buon rapporto prestazioni/prezzo e il rafforzamento del ruolo personale. Nel primo caso, i commodity cluster possono migliorare il rapporto prestazioni/prezzo di un ordine di grandezza rispetto ad architetture diverse (circa 1 euro per Mflop). I sistemi cluster ad elevate prestazioni, utilizzano moduli elementari che derivano dai sistemi di uso personale. L’amministrazione HW e SW richiedono competenze maggiormente disponibili sul mercato. Si ha un maggior senso di controllo del sistema e della sua evoluzione. Gli elementi su cui si basano i cluster (nodi di elaborazione e sistemi di rete) sono disponibili sul mercato spesso per uso personale. L’integrazione non richiede dunque moduli specializzati e i costi sono ridotti. Per la prima volta utenti e venditori hanno a disposizione un’architettura parallela stabile e indipendente. Questo garantisce persistenza a lungo termine nell’architettura e giustifica investimenti software. 14 I Sistemi di Memoria I sistemi di memoria di un elaboratore possono essere divisi in tre tipologie: memoria interna al processore, memoria principale e memoria secondaria. Ogni tipologia di memoria differisce in termini di tecnologie costruttive, prestazioni, prezzo ecc. La memoria interna costituisce sostanzialmente la parte dei registri interni alla CPU (visibili o no al programmatore) che memorizzano temporaneamente dati ed istruzioni. Le prestazioni devono dunque essere molto elevate, a tal proposito la memoria interna ha tempi di accesso dell’ordine di qualche nano secondo. Infine, a causa dei costi molto elevati le dimensioni sono nell’ordine di decine di bytes. Volendo citare una piccola nota storica, la prima macchina dotata di cache è l’Intel 486. La memoria principale è quella che viene utilizzata per memorizzare i programmi che la CPU esegue e i dati cui la stessa CPU può accedere direttamente (è importante notare che a questo tipo di memoria la CPU accede direttamente). Si tratta di una memoria veloce e di grande capacità in genere intorno alle centinaia di MBytes. Di solito sono dispositivi ad accesso casuale. La memoria secondaria viene impiegata per memorizzare dati e istruzioni che non sono di immediato interesse della CPU. Si tratta di una memoria di grandi dimensioni (GBytes) e molto più lenta della memoria RAM, all’incirca i suoi tempi di accesso sono di 6 ordini di grandezza più lenti. Dal punto di vista dei costi poi è due ordini di grandezza meno costosa della RAM. La memoria principale può essere divisa in memoria in linea (dischi magnetici) e memoria fuori linea (nastri magnetici, cd, dvd). Di solito sono dispositivi ad accesso misto. I vari tipi di memoria sono realizzati con tecnologie diverse a seconda di costo per singolo bit immagazzinato, tempo di accesso e modo di accesso (seriale o casuale). E’ importante notare che il tempo di accesso è il ritardo fra l’istante in cui avviene la richiesta e l’istante in cui il dato è disponibile al richiedente. Nel corso degli anni, seppur le prestazioni della memoria siano migliorate notevolmente, i tempi di accesso non si sono discostati così tanto dai valori precedenti. Ma vediamo in dettaglio alcune di queste tecnologie. Le memorie a semiconduttore sono realizzate su un circuito integrato che grazie alla tecnologia VLSI è in grado di fornire capacità sempre crescenti. In ogni circuito integrato sono contenute le celle di memoria, i circuiti di decodifica dell’indirizzo e l’interfacce di uscite di potenza (buffer) e i circuiti di ingresso. Lo schema di tale memoria può essere riassunto nella figura seguente: 8 15 arbitrio concentrato arbitrio distribuito Arbitro centralizzato che fornisce la possibilità di modificare agevolmente la politica di assegnazione e che presenta maggior osservabilità ovvero si può facilmente sapere cosa sta succedendo in quanto tale informazione risiede in una sola fonte (l’arbitro appunto). La politica delle priorità è contenuta all’interno dell’allocatore che risponde sempre con una sola concessione. L’unità di controllo risponde con un solo grant in base alle priorità. All’interno dell’allocatore è definita la politica di assegnazione delle risorse. Vediamo dunque due possibili versioni dell’allocatore concentrato La differenza fra i due circuiti sta nel fatto che crescendo di numero di moduli che richiedono l’accesso, nel primo caso serviranno porte con sempre più ingressi, mentre nel secondo caso ci si limita ad allungare la catena. Nel primo caso ci sono i problemi di costo e complessità dovuti a porte con n ingressi, mentre nel secondo le problematiche risiedono nei tempi di propagazione che si allungano. • Arbitro distribuito che fornisce maggiore modularità e possibilità di espansione e riconfigurazione e inoltre migliore tolleranza ai guasti. Il circuito dell’arbitro distribuito è uguale a quello concentrato, varia la distribuzione delle parti hardware. Se voglio variare la priorità posso sfruttare dei meccanismi ad anello anche se in realtà si tratta di una struttura prevalentemente fissa Esistono alcune tecniche di arbitrazione (a distribuzione decrescente): a catena o daisy-chain, polling, a richieste indipendenti. Il ciclo di acquisizione del controllo del bus è gestito da un arbitro e avviene con una sorta di meccanismo di handshake. STRATEGIA DI SOSTITUZIONE DELLE PAGINE FIFO (First-In-First-Out) Primo arrivato primo servito. Si sostituiscono le pagine in memoria da più tempo. LRU (Least Recently Used) Sostituzione della pagina usata meno recentemente. Si sostituiscono quelle pagine che è da più tempo in memoria senza essere stata referenziata. Il sistema aggiorna la coda ogni volta che una pagina viene referenziata. FIFO seconda chance e sostituzione a orologio(First-In-First-Out) Si sostituiscono le pagine in memoria da più tempo. La seconda ch’ange consiste nell’avere anche un bit di referenza. Se il bit è posto a 1 significa che la pagina è stata referenziata ed allora si rimette in coda e si azzera il bit di riferimento. In questo modo le pagine referenziate spesso rimangono in memoria. Last Recent Used (LRU): i riferimenti alle pagine disponibili (pin_count=0) vengono inseriti in una coda (L.I.F.O.) e prelevati, all’occorrenza, dalla testa. Con questa politica vengono sostituite le pagine disponibili da più tempo. I page fault si verificano quando è richiesta una pagina non presente in memoria. Se tutta la memoria è in quel momento occupata da pagine precedentemente caricate, è necessario sostituirne una con quella richiesta. La politica LRU sceglie come candidata alla sostituzione quella che non è stata riferita da più lungo tempo, con la politica FIFO quella che è stata caricata da più lungo tempo. 9.4.2 Algoritmo di rimpiazzamento FIFO • Come pagina vittima sceglie quella arrivata da più tempo in MP (non c’è bisogno di associare a ogni pagina il tempo di arrivo, ci basta una coda FIFO) • E’ in idea semplice, ma non necessariamente buona, infatti: – se la pagina contiene del codice di inizializzazione del processo, usato solo all’inizio OK, non servirà più. – ma se la pagina contiene una variabile inizializzata all'inizio e usata per tutta l’esecuzione del codice: KO! 9.4.4 Algoritmo di rimpiazzamento LRU (Least Recently Used) • Cerca di approssimare OPT sostituendo la pagina che non è stata usata da più tempo • Rispetto a OPT, guarda all'indietro anziché che in avanti: almeno il passato lo conosciamo! • LRU è un buon algoritmo di rimpiazzamento, perché si avvicina più a OPT che a FIFO, ma è difficile da implementare in modo efficiente 9