Con frecuencia, las macros conocidas como likely
y unlikely
ayudan al compilador a saber si if
generalmente se va a ingresar o omitir un Usarlo da como resultado algunas mejoras de rendimiento (más bien menores).
Empecé a usarlos recientemente, y no estoy seguro de con qué frecuencia se deben usar esas sugerencias. Actualmente lo uso con comprobación de errores if
s, que generalmente están marcados como unlikely
. Por ejemplo:
mem = malloc(size);
if (unlikely(mem == NULL))
goto exit_no_mem;
Parece correcto, pero la comprobación de errores if
ocurre con bastante frecuencia y, en consecuencia, el uso de dichas macros.
Mi pregunta es, ¿es demasiado tener likely
y unlikely
macros en cada comprobación de errores if
?
Mientras estamos en eso, ¿qué otros lugares se usan a menudo?
En mi uso actual, está en una biblioteca que hace una abstracción del subsistema en tiempo real, por lo que los programas serían portátiles entre RTAI, QNX y otros. Dicho esto, la mayoría de las funciones son bastante pequeñas y llaman directamente a una o dos funciones más. Muchos son incluso static inline
funciones.
Entonces, antes que nada, no es una aplicación que pueda perfilar. No tiene sentido "identificar cuellos de botella" ya que es una biblioteca, no una aplicación independiente.
En segundo lugar, es algo así como "Sé que esto es poco probable, también podría decírselo al compilador". No trato activamente de optimizar el if
.
fuente
likely
yunlikely
existe y lo que hacen. No encontré nada que sugiriera cuándo y dónde es mejor usarlos.Respuestas:
¿Necesita tanto rendimiento que está dispuesto a contaminar su código con eso? Es una optimización menor.
A menos que pueda responder
yes
a todo lo anterior, no se moleste con cosas como esta.Editar: en respuesta a la edición. Incluso cuando no puede crear un perfil, generalmente puede estimar puntos de acceso. Una función de asignación de memoria llamada por todos es un buen candidato, especialmente porque requiere un solo uso de la macro para funcionar en toda la biblioteca.
fuente
(un)likely
macro rara vez se usa y solo en código extremadamente crítico para el rendimiento? ¿Es una "mala práctica" usarlo con frecuencia, o simplemente "innecesario"?if (likely(x==2 || x==3)) doOneThing(); else switch(x) { ... }
, podría juzgar que el uso del programador de unif
para los valores 2 y 3 no fue simplemente una consecuencia de que el programador no supiera que C puede asociar doscase
etiquetas con un solo controlador.Si está escribiendo para x86 / x64 (y no está utilizando CPU de 20 años), la ganancia de rendimiento al usar __builtin_expect () será insignificante, si es que la hay. La razón es que las CPU modernas x86 / x64 (aunque no estoy 100% seguro sobre Atom), tienen una predicción dinámica de rama, por lo que esencialmente la CPU "aprende" sobre la rama que se toma con más frecuencia. Claro, esta información puede almacenarse solo para un número limitado de sucursales, sin embargo, solo hay dos casos posibles. Si (a) es una rama "de uso frecuente", entonces su programa se beneficiará de esa predicción de rama dinámica, y si (b) es una rama "rara", realmente no verá ningún impacto realista en el rendimiento debido a predicciones erróneas en tales ramas raras (20 ciclos de CPU de predicción errónea de ramas no son MUY malo si sucede una vez en una luna azul).
NB: esto NO implica que en la x86 / x64 moderna la importancia de la predicción errónea de la rama sea menor: cualquier rama con 50-50 de probabilidad de saltar-nojump aún incurrirá en una penalización (IIRC 10-20 ciclos de CPU), por lo que en las ramas del bucle interno puede Todavía hay que evitarlo. Solo es importante que __builtin_expect () en x86 / x64 haya disminuido (IIRC, hace unos 10-15 años más o menos), principalmente debido a la predicción dinámica de las ramas.
NB2: para otras plataformas más allá de x86 / x64, YMMV.
fuente
unlikely
notación.