Ottimizzazione statica del codice per processori pipelined Canella Matteo & Miglioli Filippo.

18
Ottimizzazione statica Ottimizzazione statica del codice per del codice per processori pipelined processori pipelined Canella Matteo & Miglioli Filippo

Transcript of Ottimizzazione statica del codice per processori pipelined Canella Matteo & Miglioli Filippo.

Page 1: Ottimizzazione statica del codice per processori pipelined Canella Matteo & Miglioli Filippo.

Ottimizzazione statica del codice Ottimizzazione statica del codice per processori pipelinedper processori pipelined

Canella Matteo & Miglioli Filippo

Page 2: Ottimizzazione statica del codice per processori pipelined Canella Matteo & Miglioli Filippo.

Lo scopoLo scopo

Scopo dell’esperienza è quello di ottimizzare staticamente il codice di un programma in linguaggio assembly DLX. Per fare questo si è utilizzato il simulatore WinDLX, che permette la visualizzazione della pipeline, dei registri interni, della memoria e dello stato di esecuzione delle singole istruzioni.

Page 3: Ottimizzazione statica del codice per processori pipelined Canella Matteo & Miglioli Filippo.

I programmi testI programmi test

Per l’esercitazione sono stati implementati due programmi. Il primo, più semplice, esegue una moltiplicazione di due numeri mediante somme parziali. Il secondo realizza l’ordinamento di un vettore di interi in memoria.

Page 4: Ottimizzazione statica del codice per processori pipelined Canella Matteo & Miglioli Filippo.

Il primo programmaIl primo programmaÈ riportata a fianco la schematizzazione in metalinguaggio del primo programma. Le variabili A e B sono i due moltiplicandi. C viene utilizzata come variabile di supporto nella quale viene memorizzato il risultato parziale. Viene sommato A a se stesso B volte.

C = 0;

WHILE B > 0 DO

C = C + A;

B = B – 1;

END_WHILE

END. r

Page 5: Ottimizzazione statica del codice per processori pipelined Canella Matteo & Miglioli Filippo.

Il primo programmaIl primo programmaVediamo ora come è stato realizzato in assembly.

I due operandi vengono memorizzati in due locazioni di memoria successive, la prima delle quali puntata dal registro R1. Il risultato dell’operazione viene riscritto sulla locazione puntata da R1.

LB R2, 0(R1) ;LEGGI A

LB R3, -15(R1) ;LEGGI B

LB R4,#0

BEQZ R3, FINE

LOOP: ADD R4,R2,R4

SUBUI R3,R3,#1

BNEZ R3,LOOP

SB 0(R1),R4

FINE: TRAP 0

Page 6: Ottimizzazione statica del codice per processori pipelined Canella Matteo & Miglioli Filippo.

Simulazione primo programmaSimulazione primo programmaIn figura vediamo il clock cycle diagram della parte del programma interessata da stalli. Si notano due stalli.

1° Stallo: Il branch è condizionato dal valore del registro R3. Tale valore è caricato nel registro dalla memoria mediante l’istruzione LB. Il processore ritarda il decode del branch (stallando la pipeline) perché il valore di R3 è disponibile solo dopo l’accesso in memoria dell’istruzione LB. Non è necessario attendere il Write Back perché è presente un feedback che rende il dato subito disponibile.

2° Stallo: il branch necessita del valore di R3, che però è disponibile solo dopo la fase di Execute dell’istruzione precedente (SUBUI). Il processore quindi introduce un ciclo di stallo. Anche in questo caso viene utilizzato il meccanismo del feedback, non occorre attendere il WB sui registri.

Si nota inoltre un ciclo perso dopo il branch, questo perché il simulatore usa una politica “Predict Untaken”, cioè esegue il fetch dell’istruzione successiva prima di sapere se il salto verrà fatto.

Page 7: Ottimizzazione statica del codice per processori pipelined Canella Matteo & Miglioli Filippo.

Simulazione primo programmaSimulazione primo programma

Sono stati inseriti nelle locazioni di memorie 0x000000ff e 0x000000f0 gli operandi, nell’esempio 3 e 4. Come si vede, il risultato (0x0c) viene memorizzato nella locazione 0x000000ff.

L’esecuzione di questo codice richiede 25 Clock Cycles.

Page 8: Ottimizzazione statica del codice per processori pipelined Canella Matteo & Miglioli Filippo.

Ottimizzazione primo programmaOttimizzazione primo programma

1° Stallo: il primo conflitto è stato risolto invertendo le due istruzioni di lettura in memoria (LB) in modo tale che il registro R3 sia pronto per l’istruzione di branch.

LB R3, -15(R1)

LB R2, 0(R1)

LB R4,#0

BEQZ R3, FINE

LOOP: SUBUI R3,R3,#1

ADD R4,R2,R4

BNEZ R3,LOOP

SB 0(R1),R4

FINE: TRAP 0

2° Stallo: è stato risolto spostando il decremento di R3 sopra l’ADD.

Page 9: Ottimizzazione statica del codice per processori pipelined Canella Matteo & Miglioli Filippo.

Ottimizzazione primo programmaOttimizzazione primo programmaVediamo che sono stati risolti tutti i conflitti. L’unico ciclo perso rimane quello dopo il branch. Questo problema non si può risolvere se non utilizzando una politica “branch delayed”, non supportata dal simulatore WinDLX.

L’esecuzione di questo codice richiede 21 Clock Cycles.

Page 10: Ottimizzazione statica del codice per processori pipelined Canella Matteo & Miglioli Filippo.

Il secondo programmaIl secondo programma

FOR I = INIZ TO (INIZ + LUNG - 1)

FOR J = I + 1 TO (INIZ + LUNG)

IF A[I] > A[J] THEN

SOS = A[J];

A[J] = A[I];

A[I] = SOS;

END_IF;

A lato è riportata la schematizzazione in metalinguaggio. Scopo del programma è ordinare un vettore di interi (A) contenuto in memoria a partire dalla locazione “INIZ” e di lunghezza “LUNG”.

Page 11: Ottimizzazione statica del codice per processori pipelined Canella Matteo & Miglioli Filippo.

Il secondo programmaIl secondo programmaLOOP: LB R8,0(R1) ;R1 PUNTATORE ALLA PRIMA LOCAZIONE

SUBI R4,R1,#15 ;R4 PUNTA ALLA LOCAZIONE SUCCESSIVA R1

SUBI R7,R2,#1 ;R7 È IL CONTATORE DEL LOOP SECONDARIO

LOOP1: LB R9,0(R4)

SLEU R5,R8,R9 ;R8 E’ MINORE UGUALE DI R9?

BNEZ R5,DOPO ;SE SI’ SALTA A “DOPO”

SB 0(R10),R8 ;SCAMBIO R8 CON R9 SE R8 È MAGGIORE DI R9

SB 8(R10),R9 ;LA LOCAZIONE PUNTATA DA R10 E LA SUCCESSIVA

LB R9,0(R10) ;SERVONO COME SUPPORTI PER LO SCAMBIO

LB R8,8(R10)

SB 0(R1),R8 ;SCRITTURA IN MEMORIA DEI DATI SCAMBIATI.

SB 0(R4),R9

DOPO: SUBI R4,R4,#15

SUBI R7,R7,#1

BNEZ R7,LOOP1

SUBI R1,R1,#15

SUBI R2,R2,#1 ;R2 È LA DIMENSIONE DELL'ARRAY, SERVE COME

SUBI R11,R2,#1 ;CONTATORE

BNEZ R11,LOOP

TRAP 0

R1 punta alla prima locazione di memoria (corrispondente alla variabile INIZ in metalinguaggio). R4 punta alla locazione di memoria successiva. R2 contiene la lunghezza del vettore (LUNG). Il programma esegue dei confronti (SLEU) e degli scambi (utilizzando due locazioni di supporto) fino ad ordinare l’intero vettore.

Page 12: Ottimizzazione statica del codice per processori pipelined Canella Matteo & Miglioli Filippo.

Simulazione secondo programmaSimulazione secondo programma

1° Stallo: L’istruzione di confronto SLEU aspetta che venga caricata nel registro R9 il contenuto della locazione puntata da R4. Questo causa uno stallo nella pipeline.

2° Stallo: Il branch condizionato aspetta R5, contenente il risultato del confronto. Notiamo due cicli di stallo: il primo è causato dall’istruzione precedente (SLEU), il secondo è quello relativo all’istruzione branch.

Senza l’ottimizzazione, il programma viene eseguito in 188 cicli di clock

Page 13: Ottimizzazione statica del codice per processori pipelined Canella Matteo & Miglioli Filippo.

Ottimizzazione secondo programmaOttimizzazione secondo programmaLOOP: LB R8,0(R1)

SUBI R4,R1,#15

SUBI R7,R2,#1

LOOP1: LB R9,0(R4)

SLEU R5,R8,R9

BNEZ R5,DOPO

SB 0(R10),R8

SB 8(R10),R9

LB R9,0(R10)

LB R8,8(R10)

SB 0(R1),R8

SB 0(R4),R9

DOPO: SUBI R4,R4,#15

BNEZ R7,LOOP1

SUBI R1,R1,#15

SUBI R2,R2,#1

SUBI R11,R2,#1

BNEZ R11,LOOP

TRAP 0

SUBI R7,R7,#1

SUBI R7,R7,#1

Soluzione 1° stallo: l’istruzione SUBI R7,R7,#1 che veniva eseguita alla fine ciclo interno LOOP1, appena prima del branch, viene spostata all’inizio del ciclo, in modo da porsi tra le due istruzioni che provocavano lo stallo. E’ possibile fare questo spostamento in quanto è indifferente eseguire il decremento del contatore all’inizio o alla fine del loop.

L’esecuzione richiede così 168 clock cycle.

Page 14: Ottimizzazione statica del codice per processori pipelined Canella Matteo & Miglioli Filippo.

Ottimizzazione secondo programmaOttimizzazione secondo programma

LOOP: LB R8,0(R1)

SUBI R4,R1,#15

SUBI R7,R2,#1

LOOP1: LB R9,0(R4)

SUBI R7,R7,#1

SLEU R5,R8,R9

BNEZ R5,DOPO

SB 0(R10),R8

SB 8(R10),R9

LB R9,0(R10)

LB R8,8(R10)

SB 0(R1),R8

SB 15(R4),R9

DOPO:

BNEZ R7,LOOP1

SUBI R1,R1,#15

SUBI R2,R2,#1

SUBI R11,R2,#1

BNEZ R11,LOOP

TRAP 0

SUBI R4,R4,#15

SUBI R4,R4,#15

Soluzione 2° stallo: lo spostamento del puntatore alla memoria R4 verso la cella successiva che veniva fatto alla fine del ciclo interno, può essere spostato all’inizio di esso. Viene cioè messo tra le due istruzioni che provocavano lo stallo. E’ necessario modificare l’offset di accesso alla cella puntata dal registro R4 nell’istruzione che riscrive in memoria i dati cambiati. Questo perché ho decrementato R4 prima di usarlo.

L’esecuzione richiede così 158 clock cycle

Page 15: Ottimizzazione statica del codice per processori pipelined Canella Matteo & Miglioli Filippo.

Simulazione secondo programmaSimulazione secondo programma

3° Stallo: nello scambio delle due celle di memoria, l’istruzione di scrittura SB che venga scritto il contenuto del registro R8 dall’istruzione precedente. Questo provoca uno stallo.

4° Stallo: il branch aspetta la fine dell’istruzione di decremento del registro R8, provocando uno stallo nella pipeline

Page 16: Ottimizzazione statica del codice per processori pipelined Canella Matteo & Miglioli Filippo.

Ottimizzazione secondo programmaOttimizzazione secondo programma

LOOP: LB R8,0(R1)

SUBI R4,R1,#15

SUBI R7,R2,#1

LOOP1: LB R9,0(R4)

SUBI R7,R7,#1

SLEU R5,R8,R9

SUBI R4,R4,#15

BNEZ R5,DOPO

SB 0(R10),R8

SB 8(R10),R9

LB R9,0(R10)

LB R8,8(R10)

SB 0(R1),R8

SB 15(R4),R9

DOPO: BNEZ R7,LOOP1

SUBI R1,R1,#15

SUBI R2,R2,#1

SUBI R11,R2,#1

BNEZ R11,LOOP

TRAP 0

SB 15(R4),R9

SB 0(R1),R8

Soluzione 3° stallo: Vengono scambiate le due istruzioni di scrittura in memoria (SB) dei registri scambiati (R8, R9).

Il programma impiega così 151 cicli di clock

Page 17: Ottimizzazione statica del codice per processori pipelined Canella Matteo & Miglioli Filippo.

Ottimizzazione secondo programmaOttimizzazione secondo programmaLOOP: LB R8,0(R1)

SUBI R4,R1,#15

SUBI R7,R2,#1

LOOP1: LB R9,0(R4)

SUBI R7,R7,#1

SLEU R5,R8,R9

SUBI R4,R4,#15

BNEZ R5,DOPO

SB 8(R10),R9

SB 0(R10),R8

LB R9,0(R10)

LB R8,8(R10)

SB 15(R4),R9

SB 0(R1),R8

DOPO: BNEZ R7,LOOP1

SUBI R1,R1,#15

SUBI R2,R2,#1

SUBI R11,R2,#1

BNEZ R11,LOOP

TRAP 0

SUBI R1,R1,#15

Soluzione 4° stallo: sposto il decremento del puntatore R1 prima del branch.

Ho risolto così tutti gli stalli. Il programma ottimizzato viene eseguito in 147 cicli di clock, cioè 41 cicli in meno della versione non ottimizzata.

Page 18: Ottimizzazione statica del codice per processori pipelined Canella Matteo & Miglioli Filippo.

Simulazione secondo programmmaSimulazione secondo programmma

Vediamo a lato l’effetto dell’ordinamento in memoria. Il vettore parte dall’indirizzo 0xff e occupa 5 posizioni. Vediamo che il vettore [7,1,5,3,2] diventa [1,2,3,5,7], ordinato.