Dada la predicción de la rama, y también el efecto de las optimizaciones del compilador, ¿qué código tiende a ofrecer un rendimiento superior?
Tenga en cuenta que bRareExceptionPresent representa una condición poco común. No es el camino normal de la lógica.
/* MOST COMMON path must branch around IF clause */
bool SomeFunction(bool bRareExceptionPresent)
{
// abort before function
if(bRareExceptionPresent)
{
return false;
}
.. function primary body ..
return true;
}
/* MOST COMMON path does NOT branch */
bool SomeFunction(bool bRareExceptionPresent)
{
if(!bRareExceptionPresent)
{
.. function primary body ..
}
else
{
return false;
}
return true;
}
optimization
theory
dyasta
fuente
fuente
Respuestas:
En el mundo de hoy, no importa mucho, si es que lo hace.
La predicción de ramificación dinámica (algo pensado durante décadas (ver Análisis de las cargas de trabajo del sistema de esquema de predicción de ramificación dinámica publicada en 1996)) es bastante común.
Un ejemplo de esto se puede encontrar en el procesador ARM. Desde el Centro de información del brazo sobre predicción de sucursales
La pregunta entonces es "¿qué es la predicción de ramificación dinámica en el procesador de brazo?" La lectura continua de la predicción de rama dinámica muestra que utiliza un esquema de predicción de 2 bits (descrito en el documento) genera información sobre si la rama se toma con fuerza o debilidad o no.
Con el tiempo (y con el tiempo me refiero a algunos pasos a través de ese bloque), esto acumula información sobre hacia dónde irá el código.
Para la predicción estática , analiza la apariencia del código y la forma en que se realiza la ramificación en la prueba, según una instrucción anterior o una más en el código:
Como lo mencionó Sparky, esto se basa en la comprensión de que los bucles con mayor frecuencia son bucles. El bucle se ramifica hacia atrás (tiene una ramificación al final del bucle para reiniciarlo en la parte superior); normalmente lo hace.
El peligro de intentar adivinar el compilador es que no sabes cómo se va a compilar ese código (y optimizarlo). Y en su mayor parte, no importa. Con la predicción dinámica, dos veces a través de la función predecirá un salto sobre la declaración de guardia para un retorno prematuro. Si el rendimiento de dos tuberías enjuagadas es de rendimiento crítico, hay otras cosas de las que preocuparse.
Es probable que el tiempo que lleva leer un estilo sobre el otro sea de mayor importancia: limpiar el código para que un humano pueda leerlo, porque el compilador funcionará bien sin importar cuán desordenado o idealizado sea el código.
fuente
Tengo entendido que la primera vez que la CPU encuentra una rama, predecirá (si es compatible) que no se toman ramas hacia adelante y hacia atrás. La razón de esto es que se supone que se toman bucles (que generalmente se ramifican hacia atrás).
En algunos procesadores, puede dar una pista en las instrucciones de ensamblaje sobre qué ruta es más probable. Los detalles de esto se me escapan en este momento.
Además, algunos compiladores de C también admiten la predicción de rama estática para que pueda decirle al compilador qué rama es más probable. A su vez, puede reorganizar el código generado o usar instrucciones modificadas para aprovechar esta información (o incluso simplemente ignorarla).
Espero que esto ayude.
fuente
__builtin_expect
?