2011-12-10 6 views
10

sto cercando di ottimizzare il codice RK4 GCC C++ utilizzando__builtin_prefetch, quanto legge?

__builtin_prefetch 

Sto avendo alcuni problemi cercando di capire come prefetch un'intera classe. Non capisco quanto del const void *addr venga letto. In modo che ho caricato i seguenti valori di from e to.

for (int i = from; i < to; i++) 
{ 
    double kv = myLinks[i].kv; 
    particle* from = con[i].Pfrom; 
    particle* to = con[i].Pto; 
    //Prefetch values at con[i++].Pfrom & con[i].Pto; 
    double pos = to->px- from->px; 
    double delta = from->r + to->r - pos; 
    double k1 = axcel(kv, delta, from->mass) * dt; //axcel is an inlined function 
    double k2 = axcel(kv, delta + 0.5 * k1, from->mass) * dt; 
    double k3 = axcel(kv, delta + 0.5 * k2, from->mass) * dt; 
    double k4 = axcel(kv, delta + k3, from->mass) * dt; 
    #define likely(x)  __builtin_expect((x),1) 
    if (likely(!from->bc)) 
    { 
      from->x += ((k1 + 2 * k2 + 2 * k3 + k4)/6); 
    } 
} 

Link: http://www.ibm.com/developerworks/linux/library/l-gcc-hacks/

+0

Non credo che ci sia molto da fare in tale micro-ottimizzazione, per scopi diversi dall'apprendimento. I cpus moderni sono molto bravi a prefetching da soli. – ronag

+1

Probabilmente, ma ho 1 funzione chiamata quasi 1 miliardo di volte. – Mikhail

risposta

15

Credo solo emettere una FETCH istruzione macchina, che recupera sostanzialmente una cache linea, la cui dimensione è specifico processore.

E potresti usare __builtin_prefetch (con[i+3].Pfrom) per esempio. Con la mia (piccola) esperienza, in un tale ciclo, è meglio precaricare diversi elementi in anticipo.

Non utilizzare __builtin_prefetch troppo spesso (ad esempio, non inserirli molti all'interno di un loop). Misurare il guadagno in termini di prestazioni se necessario e utilizzare l'ottimizzazione GCC (almeno -O2). Se sei molto fortunato, il manuale __builtin_prefetch potrebbe aumentare le prestazioni del tuo loop del 10 o 20% (ma potrebbe anche danneggiarlo).

Se un tale ciclo è cruciale per te, potresti prendere in considerazione l'esecuzione su GPU con OpenCL o CUDA (ma ciò richiede la ricodifica di alcune routine in linguaggio OpenCL o CUDA e la loro sintonizzazione sul tuo particolare hardware).

Utilizzare anche un compilatore GCC recente (l'ultima versione è 4.6.2) perché sta facendo molti progressi in queste aree.


(aggiunto nel gennaio 2018 :)

sia hardware (processori) e compilatori hanno fatto un sacco di progressi in materia di cache, così sembra che l'uso di __builtin_prefetch è meno utile oggi (nel 2018) . Assicurati di eseguire il benchmark.

+6

Sì: se hai intenzione di fare questo assicurati di fare un benchmark del tuo loop prima e dopo. C'è la possibilità che tu possa peggiorare la situazione o non fare alcuna differenza. – 111111

+4

Grazie per il tuo post. Ho fatto 3 punti di riferimento: nessuna ottimizzazione = 100%, lettura avanti [i + 3] 100% e con [i + 10] 200% +. Tutto è stato fatto con -03 e matematica veloce – Mikhail

+0

Ci sono alcuni flag di ottimizzazione oltre a '-O3' in GCC ... –

9

Legge una riga della cache. Le dimensioni della linea cache possono variare, ma è più probabile che siano 64 byte sulle CPU moderne. Se hai bisogno di leggere più linee di cache, controlla prefetch_range.