¿Cómo ha afectado la evolución de la arquitectura de la CPU al rendimiento de las llamadas a funciones virtuales?


Hace años estaba aprendiendo sobre ensamblador x86, canalización de CPU, errores de caché, predicción de ramas y todo ese jazz.

Era una historia de dos mitades. He leído sobre todas las maravillosas ventajas de las largas tuberías en el reordenamiento de instrucciones de visualización del procesador, precarga de caché, interleaving de dependencias, etc.

La desventaja era que cualquier desviación de la norma era enormemente costosa. Por ejemplo, IIRC un cierto procesador de AMD en la era temprana-gigahertz tenía un 40 ciclo penalización cada vez que se llama a una función a través de un puntero (!) y esto era aparentemente normal.

¡Este no es un número insignificante de "no te preocupes por eso"! Tenga en cuenta que "buen diseño" normalmente significa "factorizar sus funciones tanto como sea posible" y "codificar semántica en los tipos de datos", lo que a menudo implica interfaces virtuales.

La compensación es que el código que no realiza tales operaciones puede obtener más de dos instrucciones por ciclo. Estos son numbers one quiere preocuparse cuando escribe código C++ de alto rendimiento que es pesado en el diseño de objetos y ligero en el procesamiento de números.

Entiendo que la tendencia de la tubería de CPU larga se ha ido invirtiendo a medida que entramos en la era de bajo consumo. Aquí está mi pregunta:

¿La última generación de procesadores compatibles con x86 sigue sufriendo penalizaciones masivas por llamadas a funciones virtuales, predicciones de ramificaciones erróneas, etc.?

Author: spraff, 2011-08-30

1 answers

El procesador AMD en la era de los primeros gigahercios tenía una penalización de 40 ciclos cada vez que llamabas a una función

Huh.. tan grande..

Existe un método de "predicción indirecta de ramas", que ayuda a predecir el salto de funciones virtuales, SI hubo el mismo salto indirecto hace algún tiempo. Todavía hay una pena por primera y malinterpretada virt. salto de función.

El soporte varía de simple " predicted right if and only if the previous indirect branch was exactly the same" a decenas o cientos de entradas de dos niveles muy complejas con detección de alternancia periódica de 2-3 direcciones de destino para instrucción jmp indirecta única.

Hubo mucha evolución aquí...

Http://arstechnica.com/hardware/news/2006/04/core.ars/7

Introducido por primera vez con el Pentium M:... predictor de rama indirecta.

El predictor de rama indirecta

Porque las ramas indirectas cargan sus destinos de rama desde un regístrese, en lugar de tenerlos inmediatamente disponibles como es el caso de las sucursales directas, son notoriamente difíciles de predecir. El predictor de rama indirecta de Core es una tabla que almacena información del historial sobre las direcciones de destino preferidas de cada rama indirecta que encuentra el front-end. Por lo tanto, cuando el front-end encuentra una rama indirecta y la predice como tomada, puede pedir al predictor de rama indirecta que la dirija a la dirección en el BTB que probablemente la rama querer.

Http://www.realworldtech.com/page.cfm?ArticleID=rwt051607033728&p=3

La predicción indirecta de ramas se introdujo por primera vez con la microarquitectura Prescott de Intel y más tarde con el Pentium M.

Entre el 16 y el 50% de todos los errores de interpretación de las ramas fueron indirectos (29% en promedio). El valor real de la mala predicción de ramas indirectas es para muchos de los lenguajes de scripting más nuevos o de alto nivel, como Ruby, Perl o Python, que utilizan intérpretes. Otros frecuentes los culpables comunes de ramificaciones indirectas incluyen funciones virtuales (usadas en C++) y llamadas a punteros de funciones.

Http://www.realworldtech.com/page.cfm?ArticleID=RWT102808015436&p=5

AMD ha adoptado algunos de estos refinamientos; por ejemplo, agregando matrices predictoras de ramas indirectas en Barcelona y procesadores posteriores. Sin embargo, el K8 tiene predictores de ramificación más antiguos y menos precisos que el Core 2.

Http://www.agner.org/optimize/microarchitecture.pdf

3.12 Saltos indirectos en procesadores antiguos Saltos indirectos, llamadas indirectas y devoluciones pueden ir a una dirección diferente cada vez. El el método de predicción para un salto indirecto o llamada indirecta es, en procesadores más antiguos que PM y K10, simplemente para predecir que irá al mismo objetivo que la última vez que se ejecutó.

Y el mismo pdf, página 14

Predicción de salto indirecto Un salto indirecto o llamada es una instrucción de transferencia de control que tiene más de dos posibles objetivo. Un programa C++ puede generar un salto indirecto o una llamada con... una función virtual. Un salto indirecto o llamada se genera en la asamblea por especificar un registro o una variable de memoria o una matriz indexada como destino de un salto o llame a instrucción. Muchos procesadores hacen solo una entrada BTB para un salto indirecto o llamada. Esto significa que siempre será predijo ir al mismo objetivo que la última vez. A medida que la programación orientada a objetos con clases polimorfas se ha vuelto más común, existe una creciente necesidad de predecir llamadas indirectas con múltiples objetivos. Esto se puede hacer asignando una nueva entrada BTB para cada nuevo objetivo de salto que se encuentre. Historia buffer y pattern history table deben tener espacio para más de un bit de información para cada incidente de salto con el fin de distinguir más de dos posibles objetivos. El PM es el primer procesador x86 en implementar este método. La regla de predicción en p. 12 todavía se aplica con la modificación que el período máximo teórico que se puede predecir perfectamente es mn, donde m es el número de objetivos diferentes por salto indirecto, porque hay son mn diferentes subsecuencias posibles de n-longitud. Sin embargo, este máximo teórico no puede se alcanzará si excede el tamaño de la BTB o la tabla de historial de patrones.

El manual de Agner tiene un descripción del predictor de rama en muchas CPUs modernas y la evolución del predictor en cpus de cada fabricante (x86 / x86_64).

También muchos métodos teóricos de "predicción indirecta de ramas" (mira en Google scholar); incluso wiki dijo algunas palabras al respecto http://en.wikipedia.org/wiki/Branch_predictor#Prediction_of_indirect_jumps /

Para los átomos del micro de agner:

Predicción de ramas indirectas El átomo no tiene predictor de patrón para ramas indirectas según mis pruebas. Indirecto se prevé que las ramas vayan al mismo objetivo que la última vez.

Por lo tanto, para baja potencia, la predicción indirecta de ramas no es tan avanzada. También lo hace Via Nano:

Se predice que los saltos indirectos irán al mismo objetivo que la última vez.

Creo, que la tubería más corta de lowpower x86 tiene una penalización más baja, 7-20 garrapatas.

 26
Author: osgx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-04 18:56:21