La mia ipotesi è che i suggerimenti di previsione a livello di istruzione della macchina siano nel migliore dei casi un rumore, e nel peggiore dei casi un danno (spreco di byte di istruzioni) su un'architettura moderna in esecuzione speculativa, fuori dall'ordine. Fare ciò equivarrebbe a dire alla CPU di stupire - a smettere di fare le sue cose già intelligenti che è stato progettato per eseguire.
In secondo luogo, il grado in cui può essere migliorata la previsione del ramo dipende dalla causa del misprediction e dalla facilità con cui si possono misurare gli effetti delle prestazioni di, o osservare la tendenza del ramo.
Tuttavia, ritengo che il pacchetto esistente di trucchi di ottimizzazione JIT possa già migliorare la previsione dei rami in una certa misura, anche senza l'ausilio di contatori di errata previsione della CPU.
Solo un esempio di codice molto semplice:
public void repeatHistory(int value)
{
if (value == 1492)
{
landing();
}
else if (value == 1776)
{
ratifying();
}
}
Supposto che repeatHistory
venga chiamato un sacco di volte. Quando il monitor delle prestazioni basato sul campionamento analizza le statistiche dello stack di chiamata, potrebbe trovare che, per qualsiasi motivo, repeatHistory()
chiama ratifying()
si verifica più frequentemente rispetto alla precedente chiamata landing()
. Sulla base di questa osservazione, la prossima passata di generazione del codice JIT per il metodo repeatHistory
terrà conto di questo ed eseguirà una o più ottimizzazioni:
- Sposta il segno di spunta per
(value == 1776)
prima del controllo per (value == 1492)
- Tentativo di incorporare il metodo
ratifying()
nel ramo in repeatHistory()
- Se il
repeatHistory()
viene chiamato da un altro ciclo, prova a srotolare il ciclo o incorpora il metodo repeatHistory()
in quel ciclo.
- E molti altri.
Dopo aver applicato una ottimizzazione, è spesso necessario analizzare nuovamente per vedere se è possibile applicare più ottimizzazioni, perché una soluzione di successo spesso apre la porta a più opportunità.