Compilador JIT para C, C ++ y Me gusta


33

¿Existe algún compilador justo a tiempo para lenguajes compilados, como C y C ++? (¡Los primeros nombres que me vienen a la mente son Clang y LLVM! Pero no creo que actualmente lo admitan).

Explicación:

Creo que el software podría beneficiarse de la retroalimentación de perfiles de tiempo de ejecución y la recompilación agresivamente optimizada de puntos de acceso en tiempo de ejecución, incluso para lenguajes compilados a máquina como C y C ++.

La optimización guiada por perfil hace un trabajo similar, pero con la diferencia, un JIT sería más flexible en diferentes entornos. En PGO ejecutas tu binario antes de lanzarlo. Después de lanzarlo, no usaría ninguna retroalimentación de entorno / entrada recopilada en tiempo de ejecución. Entonces, si se cambia el patrón de entrada, es una prueba de penalización de rendimiento. Pero JIT funciona bien incluso en esas condiciones.

Sin embargo, creo que es controvertido si el beneficio de rendimiento de compilación JIT supera su propia sobrecarga.


1
Recurso fuera del tema fuera del sitio.
DeadMG

1
No estoy seguro de si se ajusta a la pregunta, pero para una perspectiva de usabilidad, encuentro útil el paquete Cxx en el lenguaje Julia ... le ofrece un mensaje interactivo de C ++ similar a los descritos en la respuesta @ PhilippClaßen.
Antonello

Respuestas:


33

[Ver el historial de edición para una respuesta bastante diferente que ahora es básicamente obsoleta.]

Sí, hay un par de compiladores JIT para C y / o C ++.

CLing (como se puede deducir del juego) se basa en Clang / LLVM. Actúa como un intérprete. Es decir, le das un código fuente, le das un comando para que se ejecute y se ejecuta. El énfasis aquí está principalmente en la conveniencia y la compilación rápida, no en la optimización máxima. Como tal, aunque técnicamente es una respuesta a la pregunta en sí, esto realmente no se ajusta muy bien a la intención del OP.

Otra posibilidad es NativeJIT . Esto se ajusta a la pregunta de manera algo diferente. En particular, no acepta el código fuente C o C ++, y lo compila y ejecuta. Más bien, es un pequeño compilador que puede compilar en su programa C ++. Acepta una expresión que se expresa básicamente como un EDSL dentro de su programa C ++, y genera un código de máquina real a partir de eso, que luego puede ejecutar. Esto encaja mucho mejor con un marco en el que puede compilar la mayor parte de su programa con un compilador normal, pero tiene algunas expresiones que no sabrá hasta el tiempo de ejecución, que desea ejecutar con algo que se aproxime a la velocidad de ejecución óptima.

En cuanto a la aparente intención de la pregunta original, creo que el punto básico de mi respuesta original sigue en pie: mientras que un compilador JIT puede adaptarse a cosas como datos que varían de una ejecución a la siguiente, o incluso varían dinámicamente durante una sola ejecución, la realidad es que esto hace relativamente poca diferencia, al menos como regla general. En la mayoría de los casos, ejecutar un compilador en tiempo de ejecución significa que debe renunciar a un poco de optimización, por lo que lo mejor que generalmente espera es que sea casi tan rápido como lo produciría un compilador convencional.

Aunque es posible postular situaciones en las que la información disponible para un compilador JIT podría permitirle generar un código sustancialmente mejor que un compilador convencional, las instancias de que esto suceda en la práctica parecen ser bastante inusuales (y en la mayoría de los casos donde he podido verificar está sucediendo, realmente se debió a un problema en el código fuente, no con el modelo de compilación estática).


1
¿Por qué los JIT no guardan un archivo tipo caché para que puedan omitir volver a aprender todo desde cero?
JohnMudd

3
@ JohnMudd: Sospecho que el razonamiento es la seguridad. Por ejemplo, modifique el código almacenado en caché, luego, la próxima vez que se inicie la VM, ejecutará el código que coloqué allí en lugar de lo que escribió allí.
Jerry Coffin

44
OTOH, si puede modificar cachés, también puede modificar archivos fuente.
user3125367

1
@ user3125367: Sí, pero en muchos casos el compilador realiza varias comprobaciones de tipo y puede pasar por alto si carga el código compilado directamente desde el caché. Depende del JIT, por supuesto: Java realiza un gran trabajo de cumplimiento al cargar un archivo .class (compilado), pero muchos otros hacen mucho menos (casi ninguno, en muchos casos).
Jerry Coffin

11

Sí, hay compiladores JIT para C ++. Desde una perspectiva de rendimiento puro, creo que la optimización guiada por perfil (PGO) sigue siendo superior.

Sin embargo, eso no significa que la compilación JIT aún no se use en la práctica. Por ejemplo, Apple usa LLVM como JIT para su canalización OpenGL. Ese es un dominio en el que tiene mucha más información en tiempo de ejecución, que se puede utilizar para eliminar una gran cantidad de código muerto.

Otra aplicación interesante de JIT es Cling, un intérprete interactivo de C ++ basado en LLVM y Clang: https://root.cern.ch/cling

Aquí hay una sesión de muestra:

[cling]$ #include <iostream>
[cling]$ std::cout << "Hallo, world!" << std::endl;
Hallo, world!
[cling]$ 3 + 5
(int const) 8
[cling]$ int x = 3; x++
(int) 3
(int const) 3
[cling]$ x
(int) 4

No es un proyecto de juguete, pero en realidad se usa en el CERN, por ejemplo, para desarrollar el código para el Gran Colisionador de Hadrones.


7

C ++ / CLI está jitted. De acuerdo, C ++ / CLI no es C ++ pero está bastante cerca. Dicho esto, el JIT de Microsoft no hace las optimizaciones súper inteligentes / lindas basadas en el comportamiento en tiempo de ejecución que estás preguntando, al menos no que yo sepa. Entonces esto realmente no ayuda.

http://nestedvm.ibex.org/ convierte MIPS en código de bytes de Java que luego se modificará. El problema con este enfoque de su pregunta es que descarta mucha de la información útil para cuando llega al JIT.


2

En primer lugar, supongo que querrías un jit de rastreo en lugar de un jit de método.

El mejor enfoque sería compilar el código para llvm IR, luego agregar el código de seguimiento, antes de producir un ejecutable nativo. Una vez que un bloque de código se utiliza suficientemente bien y una vez suficiente información sobre los valores (no los tipos como en los lenguajes dinámicos) de las variables, el código se puede volver a compilar (desde el IR) con protectores basados ​​en los valores de las variables.

Me parece recordar que hubo algunos progresos en la creación de jit ac / c ++ en clang bajo el nombre libclang.


1
AFAIK, libclang es la mayor parte de la funcionalidad de clang como una biblioteca. por lo tanto, puede usarlo para analizar el código fuente para crear colores de sintaxis sofisticados, pelusas, exploración de código, etc.
Javier

@Javier, eso suena bien. Creo que había una función en la biblioteca que tomó una constante cantidad * de código fuente y produjo llvm ir, pero pensando ahora, probablemente sea mejor jit basado en el ir que en la fuente.
dan_waterworth
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.