In base a ciò che ho letto su "Inside the Machine", questo approccio ai rami è più ottimale?

3

Quindi ho letto Inside the Machine di Jon Stokes. È un libro FANTASTICO, e mi ha fatto riflettere sugli effetti della programmazione sui processori ...

Dato un'unità di filiale in una CPU e un'istruzione condizionale complessa che coinvolge una chiamata di procedura (If IsTodayAHoliday (Now) > 0 Then), è più veloce incollare i risultati di quella chiamata di procedura in una variabile appena prima dell'IF affermazione? In termini di previsione di rami statici e dinamici, sembra logico che avere il valore decisionale prima che la branch unit debba valutare fa in modo che gli algoritmi di predizione siano eseguiti in modo impeccabile. È vero?

    
posta user28163 17.06.2011 - 18:35
fonte

5 risposte

14

La migliore risposta che riesco a pensare è qualcosa che ho visto ripetere più e più volte:

Don't prematurely optimize.

La versione più lunga di questo è: il compilatore (presumibilmente) conosce molto più l'architettura di destinazione di te. Dovresti scrivere il tuo codice per essere corretto e mantenibile, se l'hardware sottostante cambia, non vuoi che il tuo codice sia strettamente legato a un particolare hardware.

Per alcune architetture (Cell / BE per esempio) la penalità per uno stallo della pipeline su una previsione di salto mancata è molto più alta del costo dell'informatica che prepara entrambi i rami e fa un salto incondizionato basato sul risultato del calcolo ... ma immagino che sarebbe esattamente la cosa sbagliata da fare su un altro hardware.

Anche dalla mia esperienza nell'ottimizzazione del compilatore, è più probabile che vengano ottimizzati pattern più semplici e più riconoscibili (viene in mente lo scambio XOR swap rispetto a quello variabile temporaneo).

Spero che questo aiuti.

    
risposta data 17.06.2011 - 18:50
fonte
11

Se stai parlando della differenza tra:

if (isTodayAHoliday(now) > 0) { ... }

E

int holiday = isTodayAHoliday(now);
if (holiday > 0) { ... }

Quindi la risposta è semplice: non c'è assolutamente alcuna differenza nel codice macchina.

Ricorda che la CPU non sa nulla di funzioni o espressioni. L'istruzione branch non ha una funzione o un'espressione, richiede un valore da confrontare a zero (o qualsiasi altra cosa). Comunque lo esprimi nel linguaggio di alto livello, il compilatore deve emettere un codice che calcola quel valore, lo inserisce in un registro e poi ha l'istruzione branch.

    
risposta data 17.06.2011 - 19:24
fonte
3

Mabye, ma stai parlando di micro-ottimizzazione. Di solito è meglio lasciarlo al compilatore.

    
risposta data 17.06.2011 - 18:46
fonte
2

Se stai utilizzando una lingua superiore a quella dell'assemblatore, supponi che il compilatore sia abbastanza intelligente da memorizzare il risultato della chiamata della procedura nel posto appropriato.

Se ti trovi in un punto in cui hai bisogno di strappare un po 'di performance da una piccola porzione di codice in un ciclo stretto, quindi prova entrambe le opzioni e fai alcuni esperimenti (profilazione) per vedere quale è più veloce nel mondo reale . Quindi documenta (nei commenti) perché hai fatto quello che hai fatto per la prossima povera linfa.

    
risposta data 17.06.2011 - 19:02
fonte
2

Il modo in cui l'ho capito, in cui il valore del test è memorizzato, non farà alcuna differenza per la previsione delle branch. E se hai la chiamata all'interno dell'istruzione if, o memorizzi il risultato nella variabile temporanea, probabilmente non fa alcuna differenza per il codice generato - gli ottimizzatori sono piuttosto bravi a evitare accessi non necessari alla memoria.

Ciò che influenza l'accuratezza della previsione del ramo è la direzione in cui ci si dirige. Quanto segue potrebbe avere prestazioni diverse.

while (condition ())   {  whatever ();  }

do {  whatever (); }  while (condition ());

Uno ha un salto condizionale in avanti, uno ha un salto condizionato all'indietro. Tranne che i tipici compilatori sono abbastanza intelligenti da risolvere il problema ordinando diversamente il codice oggetto dall'origine. Inoltre, i processori apprendono le direzioni delle diramazioni previste, quindi probabilmente vedrai solo una differenza per la prima iterazione di un loop.

In breve, non preoccuparti.

Per pura curiosità, potresti voler esaminare alcuni Agner Fogs funzionare - ma non aspettarti una lettura leggera .

    
risposta data 17.06.2011 - 19:20
fonte

Leggi altre domande sui tag