39 puntos por lemonmint 2024-12-11 | Aún no hay comentarios. | Compartir por WhatsApp

Ideas erróneas sobre la optimización del compilador

  • ¿La optimización produce el programa óptimo?
    • El compilador no busca generar el programa óptimo, sino mejorar un programa simplificado.
    • La optimización del tamaño del código puede ser posible, pero la optimización del tiempo de ejecución es difícil debido a la dificultad de medirlo, la ausencia de una subestructura óptima y la imprecisión de los modelos de hardware.
    • A diferencia del tamaño del código, el tiempo de ejecución es difícil de medir con precisión, está influido por varios factores y no tiene subestructura óptima. Por ejemplo, aunque se optimicen dos bucles por separado, para optimizar todo el programa podría ser necesario fusionarlos. Además, la optimización es difícil porque no existe un modelo preciso del hardware objetivo. Por ejemplo, goSLP genera código de vectorización SLP optimizado globalmente, pero debido a que el modelo de hardware es inexacto, el programa generado no solo puede no ser óptimo, sino incluso ser más lento que LLVM.

Ideas erróneas relacionadas con la predicción de saltos

  • ¿Los pesos de salto se usan en el predictor de saltos de la CPU?
    • En la arquitectura x86, los compiladores no generan pistas de salto.
    • Los pesos de salto se usan para la colocación de bloques de código por parte del compilador. (Por ejemplo, si es muy probable que ocurra un salto, el bloque destino se coloca justo debajo del bloque actual para mejorar la localidad de la caché de instrucciones).
    • En la arquitectura reciente Intel Redwood Cove, las pistas de salto han vuelto a tener relevancia, pero en la práctica es raro que los compiladores generen estas pistas.

Ideas erróneas sobre los niveles de optimización

  • ¿-O3 genera código mucho más rápido que -O2?
    • En el caso de Clang, la diferencia de rendimiento entre -O2 y -O3 no es grande, y en GCC hay una ligera diferencia porque -O2 es menos agresivo que en Clang.
    • -O3 casi no toma en cuenta el tamaño del código, por lo que pueden aparecer problemas con la caché de instrucciones.
    • Conviene verificarlo con benchmarking.

Ideas erróneas sobre el intérprete de Javascript y el compilador JIT

  • ¿Un intérprete de Javascript hace compilación JIT en tiempo de ejecución porque no puede saber de antemano qué rutas serán hot?
    • Saber qué rutas son hot no es suficiente; también se necesita información de tipos.
    • Como la información de tipos solo se conoce en tiempo de ejecución, el compilador JIT compila el código durante la ejecución.

Ideas erróneas sobre la relación entre compilador e intérprete

  • ¿Si hay un compilador, no hace falta un intérprete?
    • En C/C++, un intérprete no resulta muy útil, pero en casos como WebAssembly puede ofrecer ventajas en facilidad de desarrollo y uso, depuración y seguridad.

Ideas erróneas sobre las etapas intermedias del compilador

  • ¿La etapa intermedia (middle-end) es independiente del objetivo o la plataforma?
    • En LLVM, la etapa intermedia no es completamente independiente del objetivo o la plataforma.

Ideas erróneas sobre la optimización de la localidad de datos

  • ¿El compilador optimiza la localidad de datos?
    • El compilador optimiza la localidad de la caché de instrucciones, pero casi no optimiza la localidad de datos.
    • Optimizar la localidad de datos requiere cambios de gran escala en el código, y los compiladores de C/C++ no pueden realizar esos cambios.
    • Para mejorar la localidad de datos, hay que usar técnicas como el diseño orientado a datos.

Ideas erróneas sobre la velocidad de compilación

  • ¿-O0 ofrece compilación rápida?
    • -O0 genera código depurable y predecible, pero no siempre garantiza una compilación rápida.
    • En general, -O0 suele ser más rápido que -O2, pero puede variar según el tamaño del proyecto y el compilador.
    • Para compilar más rápido, se puede considerar saltarse el pipeline de compilación estándar (por ejemplo, TinyCC) o generar LLVM IR directamente.

Ideas erróneas sobre la velocidad de compilación de plantillas

  • ¿Las plantillas hacen lenta la compilación?
    • Que las plantillas de C++ compilen lento se debe al modelo de compilación de C++.
    • Las plantillas en sí no degradan drásticamente la velocidad de compilación.
    • La biblioteca estándar Phobos de Dlang usa muchas plantillas, pero compila rápido.

Ideas erróneas sobre la utilidad de la compilación por separado

  • ¿La compilación por separado siempre vale la pena?
    • La compilación por separado puede hacer que el enlazado tarde mucho.
    • En muchos proyectos, los unity builds (incluir todo el código en un solo archivo) ofrecen mejor rendimiento.
    • Los unity builds aportan ventajas como optimización de todo el programa, mayor velocidad de compilación y mejores logs de errores.
    • Es raro que la compilación por separado sea mejor que los unity builds.

Ideas erróneas sobre la optimización en tiempo de enlace (LTO)

  • ¿Por qué la optimización en tiempo de enlace (LTO) ocurre en el enlazado?
    • La LTO se realiza para optimizar el programa completo.
    • En teoría, sería más razonable hacer la optimización de todo el programa en la etapa intermedia, pero debido a problemas prácticos de los sistemas de build de C/C++ (dificultad para encontrar archivos fuente y entender las relaciones de llamada), se hace en tiempo de enlace.
    • Como el linker puede encontrar todos los archivos objeto, el compilador incluye representaciones intermedias como LLVM IR en esos archivos para que el linker pueda acceder a ellas.

Ideas erróneas sobre la optimización de inlining

  • ¿El inlining es útil principalmente porque elimina la instrucción de llamada a función?
    • Eliminar la instrucción de llamada es una ventaja, pero el mayor beneficio del inlining es que habilita otras optimizaciones.
    • El inlining permite optimizaciones entre funciones.
    • Cuando el código de varias funciones se fusiona en una sola mediante inlining, se pueden aplicar técnicas de optimización intrafunción ya existentes.

Ideas erróneas sobre el papel de la palabra clave inline

  • ¿La palabra clave inline está relacionada con la optimización de inlining?
    • En C++, la palabra clave inline originalmente se usaba como pista para el optimizador, pero desde C++98 pasó a significar “se permiten múltiples definiciones”.
    • En LLVM, si existe la palabra clave inline, se agrega el atributo inlinehint y se eleva el umbral de inlining, pero su impacto no es grande.
    • Si se quiere que una función siempre sea inline, hay que usar el especificador always_inline.

Ideas erróneas sobre materiales para aprender compiladores

  • ¿LLVM es el mejor compilador para aprender?
    • LLVM tiene valor educativo, pero como soporta muchos casos de uso, es complejo y enorme.
    • Para aprender desarrollo de compiladores, conviene revisar primero compiladores más pequeños y simples como Go compiler, LDC o DMD.

Ideas erróneas sobre el comportamiento indefinido (Undefined Behavior)

  • ¿El comportamiento indefinido solo permite optimizaciones?

    • El comportamiento indefinido también puede desactivar optimizaciones.
  • ¿El compilador puede simplemente definir el comportamiento indefinido?

    • El compilador puede definir el comportamiento indefinido, pero eso puede afectar el rendimiento.
    • Sería ideal que el compilador definiera todo el comportamiento indefinido según el comportamiento de la plataforma, pero en la práctica no es fácil.

Ideas erróneas sobre la generación de código basada en IA

  • ¿Una generación de código con 99% de precisión está bien?
    • Un 99% de precisión en código generado por un compilador es, en la práctica, difícil de usar.
    • Un 1% de errores en el código provoca grandes dificultades para depurar y dar mantenimiento.
    • En proyectos grandes, un 1% de errores puede causar problemas muy graves.
    • Los LLM actuales son muy lentos en comparación con los compiladores, por lo que no son adecuados para la generación de código en línea.

Aún no hay comentarios.

Aún no hay comentarios.