Pregunta

¿Existen escenarios en los que el compilador JIT sea más rápido que otros compiladores como C++?

¿Crees que en el futuro el compilador JIT solo verá optimizaciones y características menores pero seguirá un rendimiento similar, o habrá avances que lo harán infinitamente superior a otros compiladores?

Parece que el paradigma multinúcleo es prometedor, pero no es magia universal.

¿Alguna idea?

¿Fue útil?

Solución

Sí, ciertamente existen tales escenarios.

  • La compilación JIT puede utilizar perfiles en tiempo de ejecución para optimizar casos específicos basándose en la medición de las características de lo que el código está haciendo realmente en ese momento, y puede recompilar código "activo" según sea necesario.Eso no es teórico;HotSpot de Java realmente hace esto.
  • Los JITters pueden optimizar para la configuración específica de CPU y memoria en uso en el hardware real donde se ejecuta el programa.Por ejemplo, muchas aplicaciones .NET se ejecutarán en código de 32 o 64 bits, dependiendo de dónde estén JIT.En hardware de 64 bits utilizarán más registros, memoria y un mejor conjunto de instrucciones.
  • Las llamadas a métodos virtuales dentro de un bucle cerrado se pueden reemplazar con llamadas estáticas basadas en el conocimiento en tiempo de ejecución del tipo de referencia.

Creo que habrá avances en el futuro.En particular, creo que la combinación de compilación JIT y escritura dinámica mejorará significativamente.Ya estamos viendo esto en el espacio JavaScript con Chrome V8 y TraceMonkey.Espero ver otras mejoras de magnitud similar en un futuro no muy lejano.Esto es importante porque incluso los llamados lenguajes "tipados estáticamente" tienden a tener una serie de características dinámicas.

Otros consejos

Sí, compiladores JIT pueden producir más rápido el código de máquina optimizado para el entorno actual. Pero en la práctica los programas de VM son más lentos que los programas nativos porque la propia JITing consume tiempo (más Optimización == más tiempo), y por muchos métodos JITing ellos pueden consumir más tiempo que la ejecución de ellos. Y es por eso GAC se introduce en .NET

Un efecto secundario para JITing es grande el consumo de memoria. Sin embargo, que no está relacionado con la velocidad de cálculo, puede ralentizar toda la ejecución del programa, ya que gran consumo de memoria aumenta la probabilidad de que su código se copia en disco en el almacenamiento secundario.

Perdón por mi mala Inglés.

JIT tiene ventajas, pero no veo que hacerse cargo por completo. compiladores convencionales pueden pasar más tiempo en la optimización, mientras que un JIT tiene que encontrar un equilibrio entre el exceso de optimización (tomando más tiempo del que se ahorra mediante la optimización) y demasiado poco (tomando demasiado tiempo en ejecución recta).

La respuesta obvia es utilizar cada uno donde es superior. JIT pueden aprovechar el tiempo de ejecución de perfiles con más facilidad que los optimizadores convencionales (aunque existen compiladores que puede tomar tiempo de ejecución de perfiles como entrada para guiar la optimización), y por lo general puede permitirse el lujo de hacer más optimizaciones específicas de la CPU (de nuevo, mucha convencional compiladores hacen esto, pero si va a ejecutar el ejecutable en diferentes sistemas que no pueden sacar el máximo provecho de ella). compiladores convencionales pueden dedicar más tiempo, y hacerlo de diferentes maneras.

Por lo tanto, el sistema de la lengua del futuro tendrá buenos compiladores optimizadores que emitirá el código ejecutable diseñado para su uso por los buenos compiladores JIT optimización. (Esto también es, para muchas personas, el sistema de la lengua del presente.) (El sistema de la lengua del futuro también apoyará todo, desde moderna de script Python / VB al número más feo de alta velocidad crujido.)

Como con muchas cosas, esto fue prefigurada en Lisp. Hace algún tiempo, algunos sistemas Lisp (no puedo decir muchos, no han sido todo lo que muchas implementaciones de Common Lisp) interpretado funciones Lisp mediante la compilación de ellos sobre la marcha. Lisp S-expresiones (lo que está escrito en código) son bastante sencillas descripciones de árboles de análisis, por lo que la compilación podría ir bastante rápido. Mientras tanto, un compilador de Lisp podría optimizar crujir el código donde el rendimiento fue muy importante antes de tiempo.

Básicamente, compiladores JIT tiene la oportunidad de perfilar en realidad la aplicación que se está ejecutando, y hacer un poco dando a entender sobre la base de esa información. "Fuera de línea" compiladores no serán capaces de determinar con qué frecuencia una rama de saltos y la frecuencia con que cae a través, sin insertar código especial, pida el dev para ejecutar el programa, lo puso a prueba, y recompilar.

¿Por qué esto es importante?

//code before
if(errorCondition)
{
  //error handling
}
//code after

se convierte en algo así como:

//code before
Branch if not error to Code After
//error handling
Code After:
//Code After

y procesadores x86 no predecir un salto condicional por delante en la ausencia de información de la unidad de predicción de saltos. Eso significa que predice el código de manejo de errores para funcionar, y el procesador va a tener que vaciar la tubería cuando se da cuenta de que la condición de error no se produjo.

Un compilador JIT puede ver que, e insertar una pista para la rama, por lo que la CPU predeciría en la dirección correcta. Por supuesto, los compiladores fuera de línea pueden estructurar el código de una manera que evite la mispredict, pero si alguna vez tiene que mirar a la asamblea, es posible que no le guste saltar por todas partes ....

Otra cosa que se omitió en esta conversación es que cuando se JIT una pieza de código que puede ser compilado para un sitio libre en la memoria. En un lenguaje como C ++ si el archivo DLL se basa de manera que esa parte de memoria no está disponible, tendrá que pasar por el costoso proceso de cambio de base. Es más rápido al código JIT en una dirección no utilizada a continuación rebase un DLL compilado en un espacio de memoria libre. Para empeorar las cosas, una DLL porcentualizada ya no puede ser compartida. (Ver http://msdn.microsoft.com/en-us/magazine/ cc163610.aspx )

No he estado muy impresionado con algunas de las optimizaciones en C # 3.5 de código JIT. Cosas tan simples como haciendo girar bits que es necesaria para la compresión son terriblemente ineficientes (se negó a valores de caché en un registro de la CPU y en su lugar fue a la memoria para cada operación). No sé por qué haría esto pero hace una gran diferencia y no hay nada que pueda hacer al respecto.

En lo personal creo que una buena solución sería un nivel de optimización (1-100) que se puede fijar a decir compilador JIT cuánto tiempo usted piensa que debería pasar la optimización de su código. La única otra solución sería un AOT (antes de tiempo) compilador y entonces perder muchas de las ventajas de código JIT.

Hay mucha gente que responde quizás estoy rasantes (tal vez tenga que el extremo equivocado del palo), pero para mí son dos cosas diferentes:

Que yo sepa no hay nada que le para JIT'ing C ++ compilado por ejemplo proyecto Dynamo JIT'ed código de máquina:

http://arstechnica.com/reviews/1q00/dynamo/dynamo- 1.html

Y lo hizo realmente ofrecen mejoras de velocidad en determinadas circunstancias.

La compilación de código, en el sentido de un compilador de C ++ significa tomar el código escrito en un lenguaje y convertirlo en un conjunto de instrucciones (o en algunos casos otro idioma para luego ser compilado de nuevo) que pueden ser ejecutados por algún tipo de lógica dispositivo.

por ejemplo. c ++ compilación de reunión (creo ;-) o c # compilar a IL o Java compilar a código de bytes

JIT es un proceso que ocurre durante la ejecución. La máquina de ejecutar el código analiza para ver si puede mejorarlo. Java y C # son capaces de hacer uso de ambos como el compilador prepara comandos de la máquina virtual y luego la máquina virtual tiene la oportunidad de, al menos, tener otra oportunidad en la optimización de la misma.

Algunos programas no se compilan en que se interpretan, es decir, la máquina que ejecuta los lee el código exacto que escribió. Estas máquinas tienen la oppourtunity hacer algo de JIT, pero recuerda que también pueden ser compilados estáticamente, lo que podría ser un proveedor de terceros de manera que el diseñador original de la lengua nunca tuvo la intención.

Así que para responder a su pregunta no creo JIT reemplazará compiladores estáticos. Creo que habrá siempre (siempre y cuando no es la programación por lo menos) un lugar para tomar una representación de un programa y convertir esto en un conjunto de instrucciones para una máquina de algún tipo. (Potencialmente optimizar mientras lo hace)

Sin embargo, yo creo que JIT puede llegar a ser una parte más grande de la historia, ya que el tiempo de ejecución de Java y .NET ejecutar evolucionar vez que estoy seguro de JIT recibirá las cosas mejor y dados como proyecto Dynamo supongo que hay margen para el hardware tomando JIT también, así que todo lo que su procesador no es re-optimizado basado en entorno de tiempo de ejecución.

Los compiladores JIT saben más de los sistemas de los compiladores estáticos. Añadiendo multitheading sobre la marcha específica a la máquina puede ser una mejora de la velocidad gigantesca, una vez que conseguir que funcione.

Los compiladores JIT en general tienen un poco de latencia de inicio, donde la primera ejecución del programa / código puede ser más más lento que el código precompilado. La desventaja de arranque en frío.

Otra gran ventaja de la compilación JIT es que el compilador se puede actualizar después de su programa ha sido construida y ganar nuevos trucos del compilador sin necesidad de un despliegue completo nuevo programa.

Una de las ventajas de JITing que aún no se ha mencionado es que es posible que un programa para definir un número infinito de tipos genéricos. Por ejemplo:

interface IGenericAction { bool Act<T>(); }

struct Blah<T>
{
  public static void ActUpon(IGenericAction action)
  {
     if (action.Act<T>())
       Blah<Blah<T>>.ActUpon(action);
  }
}

Llamando Blah<Int32>.ActUpon(act) llamará act.Act<Int32>(). Si ese método devuelve true, se llamará Blah<Blah<Int32>>.ActUpon(act), que a su vez llamada act.Act<Blah<Int32>>(). Si que devuelve verdadero, más llamadas se pueden realizar con un tipo aún más, están anidadas. La generación de código para todos los métodos ActUpon que podría llamarse sería imposible, pero afortunadamente no es necesario. Tipos no necesitan generarse hasta que se utilizan. Si action<Blah<...50 levels deep...>>.Act() devuelve falso, entonces Blah<Blah<...50 levels deep...>>.ActUpon no llamará Blah<Blah<...51 levels deep...>>.ActUpon y no es necesario crear este último tipo.

Un punto aún no se ha mencionado que favorece compiladores "off-line" es que tales compiladores pueden orientar de forma útil plataformas con pequeñas cantidades de RAM - incluso tan pocos como dieciséis bytes. Sin duda, todo lo que es ni remotamente un PC compatible es apto para tener millones (literalmente) de veces más memoria RAM que eso, pero creo que va a ser un tiempo antes de que uno puede encontrar una máquina con muchos megas de RAM que cuesta menos de $ 0,50 y consume menos de un milivatio de energía durante el funcionamiento.

Tenga en cuenta que los 16 bytes de RAM no es tan débil como parece, ya que los chips con tan poca memoria RAM no codifican tienda en la memoria RAM - tiene un área no volátil separada de memoria para contener código (384 bytes es el más pequeño que conozco). Eso no es mucho, por supuesto, pero es suficiente para permitir que un procesador de $ 0,25 a realizar funciones que de otro modo requerirían $ 1.00 dólares en componentes discretos.

JIT compiladores tienen más datos que pueden utilizar para influir en las optimizaciones. Por supuesto, alguien en realidad tiene que escribir código para utilizar esos datos, así que no es tan simple como eso.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top