Pregunta ¿Cómo cancelar la predicción de rama? [cerrado]


De la lectura esta Me encontré con las siguientes dos citas:

Primera cita:

Un caso típico de comportamiento de ramificación impredecible es cuando el resultado de la comparación depende de los datos.

Segunda cita:

Sin ramas significa sin errores

Para mi proyecto, trabajo en datos dependientes y realizo muchos if y switch declaraciones. Mi proyecto esta relacionado con Big Data Por eso tiene que ser lo más eficiente posible. Así que quise probarlo en los datos proporcionados por el usuario, para ver si la predicción de bifurcación en realidad ralentiza mi programa o ayuda. A partir de la lectura aquí:

La demora en la predicción es entre 10 y 20 ciclos de reloj.

Lo que más me sorprendió fue:

La eliminación de las ramas no solo mejora el rendimiento del código en tiempo de ejecución, sino que también ayuda al compilador a optimizar el código.

¿Por qué usar la predicción de rama entonces?

¿Hay una manera de forzar al compilador a generar código ensamblador sin ramas? o deshabilitar la predicción de rama para que la CPU? entonces puedo comparar ambos resultados?


5
2018-02-10 20:24


origen


Respuestas:


para ver si la predicción de rama realmente ralentiza mi programa o ayuda

La predicción de rama no ralentiza los programas. Cuando las personas hablan sobre el costo de las predicciones perdidas, hablan de cuánto más costosa es una sucursal predicha en comparación con una rama predicha correctamente.

Si la predicción de rama no existiera, todas las ramas serían tan caras como una predicción errónea.

Entonces, lo que realmente significa que el "retraso en la predicción errónea es entre 10 y 20 ciclos de reloj" es que una predicción de rama exitosa le ahorra de 10 a 20 ciclos.

La eliminación de las ramas no solo mejora el rendimiento del código en tiempo de ejecución, sino que también ayuda al compilador a optimizar el código.

¿Por qué usar la predicción de rama entonces?

¿Por qué usar la predicción de ramas sobre la eliminación de ramas? No deberias. Si un compilador puede eliminar ramas, lo hará (asumiendo que las optimizaciones están habilitadas), y si los programadores pueden eliminar ramas (suponiendo que no dañe la legibilidad o que sea una pieza de código de rendimiento crítico), deberían hacerlo.

Eso difícilmente hace inútil la predicción de rama. Incluso si elimina tantas ramas como sea posible de un programa, todavía contendrá muchas, muchas ramas. Entonces, debido a esto y por lo caras que son las ramas impredecibles, la predicción de las ramas es esencial para un buen desempeño.

¿Hay una manera de forzar al compilador a generar código ensamblador sin ramas?

Un compilador optimizador ya eliminará las ramas de un programa cuando pueda (sin cambiar la semántica del programa), pero, a menos que estemos hablando de una muy simple int main() {return 0;}programa de tipo, es imposible eliminar todas las ramas. Los bucles requieren ramas (a menos que estén desenrollados, pero eso solo funciona si conoce el número de iteraciones antes de tiempo) y también lo hacen la mayoría de las declaraciones if y switch. Si puedes minimizar el número de ifs, switches y bucles en tu programa, genial, pero no podrás eliminarlos todos.

o deshabilitar la predicción de rama para que la CPU? ¿Entonces puedo comparar ambos resultados?

Que yo sepa, es imposible desactivar la predicción de bifurcación en las CPU x86 o x86-64. Y como dije, esto nunca mejoraría el rendimiento (aunque podría hacerlo predecible, pero eso no suele ser un requisito en los contextos donde se usan estas CPU).


8
2018-02-10 21:53



Los procesadores modernos tienen tuberías que permiten que la CPU funcione mucho más rápido de lo que sería capaz de hacer de otra manera. Esta es una forma de paralelismo en la que comienza a procesar una instrucción unos cuantos ciclos de reloj antes de que la instrucción sea realmente necesaria. Mira aquí aquí para más detalles.

Esto funciona muy bien hasta que golpeamos una rama. Ya que estamos saltando, el trabajo que está en la tubería ya no es relevante. La CPU necesita lavar la tubería y reiniciar nuevamente. Esto causa un retraso de algunos ciclos de reloj hasta que la tubería se llena nuevamente. Esto se conoce como una parada de tubería.

Las CPU modernas son lo suficientemente inteligentes cuando se trata de saltos incondicionales para seguir el salto al rellenar la tubería, evitando así el bloqueo. Esto no funciona cuando se trata de bifurcar, ya que la CPU no sabe exactamente dónde irá el salto.

La Predicción de Rama intenta resolver este problema haciendo una conjetura sobre qué rama seguirá la CPU antes de evaluar completamente el salto. Esto (cuando funciona) evita el bloqueo.

Como casi toda la programación implica tomar decisiones, la bifurcación es inevitable. Pero ciertamente uno puede escribir código con menos ramas y, por lo tanto, disminuir los retrasos causados ​​por la predicción errónea. Una vez que nos estamos bifurcando, la predicción de la bifurcación al menos nos permite la oportunidad de hacer las cosas bien y no tener un bloqueo de la CPU.


5
2018-02-10 21:39