Modelo moderno de costo x86


Estoy escribiendo un compilador JIT con un motor x86 y aprendiendo ensamblador x86 y código máquina sobre la marcha. Usé ARM assembler hace unos 20 años y estoy sorprendido por la diferencia en los modelos de costo entre estas arquitecturas.

Específicamente, los accesos a memoria y las ramas son caros en ARM, pero las operaciones de pila equivalentes y los saltos son baratos en x86. Creo que las CPU x86 modernas hacen optimizaciones mucho más dinámicas que los núcleos ARM y me resulta difícil anticipar sus effects.

¿Cuál es un buen modelo de costo a tener en cuenta al escribir ensamblador x86? ¿Qué combinaciones de instrucciones son baratas y cuáles son caras?

Por ejemplo, mi compilador sería más simple si siempre generara la forma larga para cargar enteros o saltar a compensaciones incluso si los enteros fueran pequeños o las compensaciones cercanas, pero ¿afectaría esto al rendimiento?

No he hecho ningún punto flotante todavía, pero me gustaría llegar a él pronto. ¿Hay algo que no sea obvio ¿sobre la interacción entre el código normal y el flotante?

Sé que hay muchas referencias (por ejemplo, Michael Abrash) sobre la optimización x86, pero tengo la corazonada de que nada más que unos pocos años no se aplicará a las CPU x86 modernas porque han cambiado mucho últimamente. Estoy en lo cierto?

Author: Peter Cordes, 2012-03-31

6 answers

La mejor referencia es el Intel Optimization Manual, que proporciona información bastante detallada sobre peligros arquitectónicos y latencias de instrucción para todos los núcleos Intel recientes, así como un buen número de ejemplos de optimización.

Otra excelente referencia es Los recursos de optimización de Agner Fog, que tienen la virtud de cubrir también los núcleos AMD.

Tenga en cuenta que los modelos de costos específicos son, por naturaleza, específicos de la microarquitectura. No hay tal cosa como un "modelo de costo x86" que tiene cualquier tipo de validez real. A nivel de instrucción, las características de rendimiento de Atom son muy diferentes de i7.

También me gustaría señalar que los accesos de memoria y las ramas no son realmente "baratos" en núcleos x86 it es solo que el modelo de ejecución fuera de orden se ha vuelto tan sofisticado que puede ocultar con éxito el costo de ellos en muchos escenarios simples.

 33
Author: Stephen Canon,
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-03-31 15:10:05

Las latencias de instrucción y rendimiento de Torbjörn Granlund para los procesadores AMD e Intel x86 también son buenas.

Editar

El documento de Granlund se refiere al rendimiento de instrucciones en el contexto de cuántas instrucciones de un determinado tipo se pueden emitir por ciclo de reloj (es decir, se realizan en paralelo). También afirma que la documentación de Intel no siempre es precisa.

 5
Author: Olof Forshell,
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-04-05 12:34:50

Por si sirve de algo, solía haber un asombroso libro llamado "Inner Loops" de Rick Booth que describía con gran detalle cómo microoptimizar manualmente el código de ensamblaje IA-86 para los procesadores Intel 80486, Pentium, Pentium Pro y Pentium MMX, con muchos ejemplos útiles de código del mundo real (hash, memoria móvil, generación de números aleatorios, compresión Huffman y JPEG, multiplicación de matrices).

Desafortunadamente, el libro no se ha actualizado desde su primera publicación en 1997 para nuevos procesadores y arquitecturas de CPU. Sin embargo, todavía lo recomendaría como una introducción suave a temas como:

  • qué instrucciones son generalmente muy baratas, o baratas, y cuáles no son
  • qué registros son los más versátiles (es decir, no tienen un significado especial / no son el registro predeterminado de algunas instrucciones)
  • cómo emparejar instrucciones para que se ejecuten en paralelo sin detener una canalización
  • diferente tipos de puestos
  • predicción de ramas
  • qué tener en cuenta con respecto a las cachés del procesador
 3
Author: stakx,
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-05-21 09:06:37

Vale la pena mirar los backends existentes compiladores de código abierto como GCC y LLVM. Estos tienen modelos para los costos de instrucción y también modelos de máquina decentes (pero idealizados) (por ejemplo, ancho de problema, tamaños de caché, etc.).

 1
Author: BeeOnRope,
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
2016-06-23 05:08:27

Por supuesto, los informes de Agner Fog y el Manual de Referencia de Optimización de Arquitecturas Intel® 64 e IA-32 son referencias necesarias y excelentes. AMD también tiene un manual de optimización:

  • Guía de Optimización de Software para Procesadores de la Familia AMD 15h

Sin embargo, dos herramientas de Intel son esenciales para comprender las secuencias de código:

  • Analizador de Código de Arquitectura Intel®
  • Intel® VTune™

IACA es su modelo de costos. Lo uso en OSX pero VTune solo se ejecuta en Windows y Linux.

También puede profundizar en la literatura de patentes de Intel y varios documentos de Intel para comprender mejor cómo funcionan las cosas:

  • La Microarquitectura Intel Core de Próxima Generación
  • Haswell: El Procesador Intel Core de Cuarta Generación
  • Caché de micro-operación: Un frontend consciente de energía para la longitud de instrucción variable ISA
 1
Author: Olsonist,
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
2016-08-08 00:30:50

Estoy escribiendo un compilador JIT con un motor x86 y aprendiendo x86 ensamblador y código de máquina sobre la marcha.

El problema esencial aquí es que un compilador JIT no puede permitirse pasar una gran cantidad de tiempo micro-optimizando. Debido a que la "optimización" ocurre en tiempo de ejecución, el costo de hacer optimizaciones debe ser menor que el tiempo ahorrado por las optimizaciones (de lo contrario, la optimización se convierte en una pérdida neta de rendimiento).

Para 80x86 hay múltiples CPU diferentes con diferentes comportamientos / características. Si toma en cuenta las características específicas de la CPU real, entonces el costo de hacer la optimización aumenta y se topa directamente con una barrera de" costos más de lo que gana". Esto es especialmente cierto para cosas como "programación de instrucciones ideal".

Afortunadamente, la mayoría (pero no todas) las CPU modernas 80x86 tienen varias características (fuera de orden, ejecución especulativa, hiper-threading) para mitigar (algunos de) los costos de rendimiento causados por " menos que perfecta " optimización. Esto tiende a hacer que las optimizaciones costosas sean menos beneficiosas.

Lo primero que va a querer hacer es identificar qué piezas de código deben optimizarse y cuáles no. Las cosas que no se ejecutan con frecuencia (por ejemplo, código de inicialización "solo ejecutado una vez") no deben optimizarse en absoluto. Solo se ejecutan con frecuencia piezas (por ejemplo, bucles internos, etc.) donde vale la pena molestar. Una vez que haya identificado una pieza que vale la pena optimizar la pregunta entonces se convierte en " ¿cuánto?".

Como una sobre-generalización cruda; esperaría que (en promedio) el 90% del código no valga la pena optimizarlo en absoluto, y para el 9% del código solo vale la pena hacer alguna optimización genérica. El 1% restante (que podría beneficiarse de una optimización extensa en teoría) terminará siendo demasiado molesto para que el desarrollador del compilador JIT se moleste en la práctica (y resultaría en una pesadilla de complejidad/verificabilidad masiva, por ejemplo, " errores que solo existen cuando se ejecutan en algunos escenarios de CPU).

 0
Author: Brendan,
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
2016-08-08 04:15:04