¿Cuál es la relación entre llamadas probables e improbables en Kernel? Mientras buscaba en la fuente del núcleo, encontré estas declaraciones.
# define likely(x) __builtin_expect(!!(x), 1)
# define unlikely(x) __builtin_expect(!!(x), 0)
¿Alguien podría arrojar algo de luz?
Respuestas:
Son sugerencias del compilador para GCC. Se usan en condicionales para decirle al compilador si es probable que se tome una rama o no. Puede ayudar al compilador a establecer el código de manera óptima para el resultado más frecuente.
Se usan así:
Debe usarse con mucho cuidado (es decir, en función de los resultados reales del perfil de sucursal). Una pista incorrecta puede degradar el rendimiento (obviamente).
Algunos ejemplos de cómo se puede optimizar el código se encuentran fácilmente mediante la búsqueda
GCC __builtin_expect
. Esta publicación de blog sobre la optimización de gcc: __builtin_expect, por ejemplo, detalla un desmontaje con ella.El tipo de optimizaciones que se pueden hacer es muy específico del procesador. La idea general es que, a menudo, los procesadores ejecutarán el código más rápido si no se ramifica / salta por todas partes. Cuanto más lineal sea, y cuanto más predecibles sean las ramas, más rápido se ejecutará. (Esto es especialmente cierto para procesadores con tuberías profundas, por ejemplo).
Por lo tanto, el compilador emitirá el código de modo que la rama más probable no implique un salto si eso es lo que prefiere la CPU de destino, por ejemplo.
fuente
Vamos a descompilar para ver qué hace GCC 4.8 con él
Sin esperar
Compile y descompile con GCC 4.8.2 x86_64 Linux:
Salida:
El orden de las instrucciones en la memoria no cambió: primero el
printf
y luegoputs
elretq
retorno.Con esperar
Ahora reemplace
if (i)
con:y obtenemos:
El
printf
(compilado a__printf_chk
) se movió al final de la función, despuésputs
y al regreso para mejorar la predicción de rama como se menciona en otras respuestas.Entonces es básicamente lo mismo que:
Esta optimización no se realizó con
-O0
.Pero buena suerte al escribir un ejemplo que funciona más rápido con
__builtin_expect
que sin, las CPU son realmente inteligentes en esos días . Mis ingenuos intentos están aquí .C ++ 20
[[likely]]
y[[unlikely]]
C ++ 20 ha estandarizado esas incorporaciones de C ++: /programming/51797959/how-to-use-c20s- probably -un Improved-attribute-in-if-else-statement Probablemente (un juego de palabras!) haz lo mismo.
fuente