2011-12-10 9 views
10

estoy tratando de optimizar algún código RK4 GCC C++ mediante__builtin_prefetch, ¿cuánto lee?

__builtin_prefetch 

Estoy teniendo algunos problemas tratando de encontrar la manera de captación previa a toda una clase. No entiendo la cantidad de const void *addr que se lee. De modo que tengo los siguientes valores de from y to cargados.

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); 
    } 
} 

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

+0

No creo que haya mucho sentido en dicha micro-optimización, para fines que no sean el aprendizaje. Las CPUs modernas son muy buenas en la captación previa por sí mismas. – ronag

+1

Probablemente, pero tengo 1 función que se llama casi mil millones de veces. – Mikhail

Respuesta

15

Creo que acaba de emitir una instrucción de máquina FETCH, que básicamente se obtiene una línea de caché, cuyo tamaño es de procesador específico.

Y podría usar __builtin_prefetch (con[i+3].Pfrom) por ejemplo. Por mi (pequeña) experiencia, en ese circuito, es mejor prearchivar varios elementos de antemano.

No utilice __builtin_prefetch con demasiada frecuencia (es decir, no coloque muchos de ellos dentro de un bucle). Mida la ganancia de rendimiento si los necesita y use la optimización de GCC (al menos -O2). Si tiene mucha suerte, el manual __builtin_prefetch podría aumentar el rendimiento de su ciclo en un 10 o 20% (pero también podría dañarlo).

Si tal bucle es crucial para usted, puede considerar ejecutarlo en GPU con OpenCL o CUDA (pero eso requiere recodificar algunas rutinas en lenguaje OpenCL o CUDA, y sintonizarlas en su hardware particular).

Utilice también un compilador GCC reciente (la última versión es 4.6.2) porque está haciendo un gran progreso en estas áreas.


(añadido en enero de 2018 :)

tanto de hardware (procesadores) y compiladores han hecho muchos progresos en relación con las memorias caché, por lo que parece que el uso de __builtin_prefetch es menos útil hoy en día (en 2018) . Asegúrate de hacer benchmarck.

+6

Sí: si va a hacer esto, asegúrese de comparar su ciclo antes y después. Existe la posibilidad de que empeore o no haga ninguna diferencia. – 111111

+4

Gracias por su publicación. Hice 3 puntos de referencia: sin optimización = 100%, leyendo por delante [i + 3] 100% y con [i + 10] 200% +. Todo se hizo con -03 y matemáticas rápidas – Mikhail

+0

Hay algunos indicadores de optimización además de '-O3' en GCC ... –

9

Lee una línea de caché. El tamaño de la línea de caché puede variar, pero es más probable que sea de 64 bytes en las CPU modernas. Si necesita leer varias líneas de caché, consulte prefetch_range.