Visualizza messaggio singolo
Vecchio 28-11-2007, 18.33.22   #4 (permalink)
MarcoGT
VV.com Aficionados
 
L'avatar di MarcoGT
 
Data registrazione: 27-11-2007
Residenza: near COD NDB
Messaggi: 687
MarcoGT is on a distinguished road
Predefinito

...continua...

Se la cache on-chip ha il vantaggio di aumentare le prestazioni, la tecnologia attuale e il numero di transistori disponibili ne limitano la dimensione massima. Attualmente 64 Kbyte (32 per i dati e 32 per le istruzioni) rappresentano il limite della cache di primo livello, e la sua implementazione richiede molti milioni di transistor. Questi fattori limitanti della cache on-chip aumentano l‘importanza della cache di secondo livello.
Il tempo di accesso di molti dei dispositivi RAM attualmente disponibili è piuttosto elevato rispetto al tempo di clock del processore, e ciò forza i progettisti a trovare soluzioni alternative. L’interleaving della cache è uno degli espedienti utilizzati, dato che permette la sovrapposizione delle richieste in memoria da parte del processore. Questa tecnica si può applicare sia alla memoria principale che alla cache; il più comune è l’interleaving a due o a quattro vie. Questo perché aumentando l’interleaving si riesce a nascondere gran parte del tempo di accesso, ma aumenta considerevolmente anche la complessità richiesta per supportarlo.

2) Le dipendenze dei dati

In un programma, le istruzioni vengono caricate dalla cache istruzioni, decodificate ed eseguite. Il dato corrispondente è spesso caricato da un registro, manipolato in un’ALU, e il risultato viene rimesso nello stesso registro o in un altro.Se l’istruzione successiva della sequenza richiede il risultato dell’istruzione precedente per poter essere eseguita, avviene una dipendenza di dati. Per quelle istruzioni che richiedono molti cicli per essere completate, ci può essere un impatto notevole sulle prestazioni nel caso vi siano delle dipendenze. Alcune di queste possono essere eliminate semplicemente riarrangiando il programma in modo che il risultato di una data istruzione non venga utilizzato dalle prime istruzioni seguenti.
Un modo per alleviare il problema delle dipendenze dei dati è utilizzare l’esecuzione fuori ordine con ridenominazione dei registri.

3) Diramazioni (salti condizionati)
Tutti i programmi di computer contengono diramazioni (branch). Alcune sono non condizionali, cioè il flusso del programma viene interrotto non appena l’istruzione di branch viene eseguita; altre sono condizionali, cioè il branch viene eseguito solo se certe condizioni vengono soddisfatte.

Ad esempio una tipica istruzione branch di un processore MIPS (usato soprattutto in ambito dell'automazione industriale ma credo anche su alcune versione del Nintendo) può essere:

beq $s1, $s2, L1

beq = branch if equal; questa istruzione assembler confronta il contenuto dei registri $s1 e $s2 (la ALU effettua un'operazione aritmetica, in questo caso una sottrazione) e se sono uguali salta all'etichetta L1, se il contenuto dei due registri non è uguale, continua con l'esecuzione del programma.

Le interruzioni del flusso del programma sono presenti in tutti i software, e l’hardware può solo cercare di adeguarsi ai branch nel modo più efficiente possibile.
Quando viene presa una diramazione, il nuovo indirizzo al quale il programma deve riiniziare può essere nella cache secondaria oppure no; a seconda di dove è situato il nuovo blocco di istruzioni la latenza aumenta o diminuisce. Poiché il tempo di accesso della memoria principale e della cache secondaria sono molto maggiori del tempo di accesso della cache on chip, il branching spesso degrada le prestazioni del processore.

Questo problema è ancora più importante nelle macchine superscalari, dove ad ogni ciclo vengono eseguite più istruzioni. In un certo momento, infatti, a seconda della dimensione della pipeline, numerose istruzioni possono essere in vari stadi di esecuzione; quando viene presa una diramazione, non si conoscono il numero di cicli che saranno necessari per la sua esecuzione.
L’implementazione del branching è un importante problema architetturale. Per migliorare le prestazioni molte architettura attuali incorporano una circuiteria per la predizione delle diramazioni, la quale può essere implementata in vari modi.

RIDUZIONE DELLA LATENZA DELLE MEMORIE

La riduzione della latenza della memoria è un passo critico nell’aumentare le prestazioni di un processore.

1)Interfaccia a larga banda con la cache secondaria

Un’interfaccia ideale cache secondaria-processore dovrebbe essere sempre in grado di ricevere una richiesta di dati dal processore e di soddisfare questa richiesta nel ciclo di clock successivo; ci si riferisce a questo comportamento come uno "zero wait state". Per progettare una cache secondaria che sia in grado di raggiungere questo tipo di prestazioni, l’interfaccia deve essere studiata in modo da riuscire a trasmettere i dati sempre alla massima velocità possibile.

Il bus dati e il bus indirizzi per molti processori costituiscono l’interfaccia con l’intero sistema: il processore può accedere a qualsiasi tipo di dispositivo in ogni momento.

Quando avviene un cache miss, viene spedito sul bus un indirizzo, e si accede alla cache secondaria, trasferendo i dati richiesti alla cache on-chip.

Se avviene un cache miss in un bus di sistema condiviso, e il processore sta utilizzando il bus esterno per leggere o scrivere su qualche altro dispositivo, l’accesso alla cache secondaria deve attendere finchè non si sono liberati i bus dati e indirizzi; ciò può richiedere molti cicli di clock, a seconda della periferica a cui si accede.

In un sistema con bus dedicato i bus dei dati, degli indirizzi e di controllo per la cache secondaria sono separati dai bus che si interfacciano con il resto del sistema. In questo modo gli accessi alla cache secondaria in caso di miss vengono garantiti sempre, qualsiasi cosa stia facendo il sistema.

2) Accesso a blocchi

Quando avviene un cache miss on-chip, esiste un numero di byte, solitamente programmabile, che viene trasferito sul bus ogni volta che si accede alla cache secondaria. Questo numero è la dimensione di una linea di cache; per le architetture attuali la dimensione classica è di 32 byte.
Il numero di accessi richiesto per effettuare il riempimento di una linea dipende dalla dimensione del bus di dati esterno del processore. Per esempio, un processore con bus dati a 64 bit che si interfaccia con una memoria a 64 bit impiegherà quattro accessi alla cache secondaria per riempire una linea di cache da 32 byte. Per completare tutto ciò il processore deve generare quattro indirizzi separati e guidare ognuno sul bus indirizzi esterno tramite appropriati segnali di controllo.

Utilizzando l’accesso a blocchi il processore deve invece generare solo l’indirizzo iniziale della sequenza, mentre gli altri tre indirizzi vengono generati dalla logica di controllo della cache.

3) Interleaving

L’interleaving è una tecnica di progetto utilizzata per aumentare la larghezza di banda della memoria; tale tecnica può essere applicata sia alla cache secondaria che alla memoria principale.
Il sistema di memoria più semplice è quello con un solo banco di memoria. Quando si accede a tale banco, deve trascorrere un certo intervallo temporale prima di un secondo accesso; quaesto intervallo dipende sia dal progetto del sistema sia dalla velocità dei dispositivi di memoria utilizzati. Se sono presenti più banchi, allora l’accesso ai banchi può essere sovrapposto. L’abilità di sovrapporre tali accessi aiuta a nascondere le latenze della memoria e diventa sempre più importante al crescere della dimensione dei dati richiesti.

Una tipica memoria con interleaving consiste in banchi pari e dispari. Per esempio, il processore richiede dei dati ad un indirizzo pari, così il controller della memoria inizia un ciclo al banco pari. Una volta che l’indirizzo è stato raggiunto dalla logica di controllo della memoria, il processore può generare un nuovo indirizzo, il più delle volte nel ciclo di clock successivo. Se il nuovo indirizzo si riferisce ad un banco dispari, l’accesso alla memoria può iniziare immediatamente; in questo modo, non appena il banco pari ha completato l'operazione, il banco dispari è già pronto a fornire il dato. Pertanto più a lungo si riesce a minimizzare gli accessi sequenziali, più ci si avvicina alle prestazioni di tipo "zero wait state".

I più comuni sistemi di memoria con interleaving sono quelli a due e a quattro vie; il numero di banchi e la larghezza di banda di ciascuno sono spesso determinati dal processore.

4) Cache non bloccante

In una tipica implementazione il processore agisce sulla cache finchè avviene un cache miss. A questo punto, trascorre un certo numero di cicli prima che i dati vengano riportati nella cache on-chip, permettendo la ripresa dell’esecuzione. Questo tipo di implementazione è detto bloccante, dato che non si può accedere alla cache finchè non viene risolto il cache miss.

La cache di tipo non bloccante invece, permette accessi consecutivi anche in caso di cache miss. In questo caso, per aumentare le prestazioni globali del sistema, è cruciale localizzare il prima possibile i miss e effettuare i passi necessari per risolverli.

5) Prefetch

Il prefetching è una tecnica con cui il processore può richiedere un blocco di cache prima del momento in cui è effettivamente necessario. L’istruzione di prefetch deve essere integrata nel set di istruzioni, e deve esserci un appropriato hardware per eseguirla.
Per esempio, supponiamo che il compilatore stia avanzando in modo sequenziale attraverso un segmento di codice. Il compilatore può fare l’ipotesi che questa sequenza continuerà oltre il range degli indirizzi disponibili nella cache di primo livello, e può richiedere un’istruzione di prefetch, la quale carica il blocco di istruzioni successivo nella cache di secondo livello. Quindi, quando il processore richiede la sequenza successiva, questa può essere eseguita ad una frequenza maggiore; se per qualche motivo tale blocco non è necessario, l’area nella cache secondaria viene semplicemente sovrascritta da altre istruzioni.
MarcoGT non è connesso   Rispondi citando