Domanda

Ci sono scenari in cui il compilatore JIT è più veloce di altri compilatori come C ++?

Pensi che in futuro compilatore JIT sarà solo vedere ottimizzazioni minori, caratteristiche, ma seguire una performance simile, o ci saranno le innovazioni che renderanno infinitamente superiore ad altri compilatori?

Sembra che il paradigma multicore ha qualche promessa, ma non è magia universale.

Tutte le comprensioni?

È stato utile?

Soluzione

Sì, ci sono certamente tali scenari.

  • compilazione JIT può utilizzare runtime profiling per ottimizzare casi specifici basati sulla misurazione delle caratteristiche di ciò che il codice è in realtà facendo in questo momento, e può ricompilare il codice "a caldo", se necessario. Questo non è teorica; HotSpot Java realmente fa questo.
  • Jitters in grado di ottimizzare la configurazione specifica CPU e la memoria in uso sul hardware reale in cui il programma sembra essere in esecuzione. Ad esempio, molte applicazioni NET funzionerà in 32 bit o codice a 64 bit, a seconda di dove sono JITted. Su po hardware a 64 useranno più registri, memoria e una migliore set di istruzioni.
  • chiamate a metodi virtuali all'interno di un ciclo stretto può essere sostituito con chiamate statiche basate sulla conoscenza runtime del tipo di riferimento.

Credo che ci saranno scoperte in futuro. In particolare, penso che la combinazione di compilazione JIT e tipizzazione dinamica sarà notevolmente migliorata. Stiamo già vedendo questo nello spazio di JavaScript con V8 e TraceMonkey di Chrome. Mi aspetto di vedere altri miglioramenti di grandezza simile in un futuro non troppo lontano. Questo è importante perché anche le cosiddette lingue "staticamente tipizzati" tendono ad avere un certo numero di caratteristiche dinamiche.

Altri suggerimenti

Sì, compilatori JIT in grado di produrre più veloce codice macchina ottimizzato per l'ambiente corrente. Ma in pratica i programmi di macchine virtuali sono più lenti rispetto ai programmi nativi perché JITing si consuma tempo (più Optimization == più tempo), e per molti metodi JITing li possono consumare più tempo di quanto la loro esecuzione. Ed è per questo GAC è stato introdotto in .NET

Un effetto collaterale per JITing è grande consumo di memoria. Tuttavia che non è legata alla velocità di calcolo, si può rallentare l'intera esecuzione del programma, perché il consumo di memoria di grandi dimensioni aumenta la probabilità che il codice sarà paging alla memoria secondaria.

Mi scusi per il mio cattivo inglese.

JIT ha dei vantaggi, ma io non lo vedo completamente presa in consegna. compilatori convenzionali possono passare più tempo a ottimizzare, mentre un JIT ha bisogno di trovare un equilibrio tra il troppo ottimizzazione (prendendo più tempo di quanto viene salvato dalla ottimizzazione) e troppo poco (prendendo troppo tempo in esecuzione dritto).

La risposta ovvia è quella di utilizzare ogni dove è superiore. Squadre investigative comuni possono usufruire di run-time di profili più facilmente di ottimizzatori convenzionali (anche se ci sono compilatori che può prendere di runtime profili come input per guidare ottimizzazione), e possono generalmente permettersi di fare ulteriori ottimizzazioni specifiche della CPU (ancora una volta, un sacco di convenzionale compilatori lo fanno, ma se si prevede di eseguire il file eseguibile su sistemi diversi che non possono trarre il massimo vantaggio di esso). compilatori convenzionali possono passare più tempo, e lo fa in modi diversi.

Di conseguenza, il sistema di linguaggio del futuro avrà buoni compilatori ottimizzanti che emetterà codice eseguibile progettato per l'utilizzo da buoni compilatori JIT ottimizzazione. (Questo è anche, per molte persone, il sistema di lingua del presente.) (Il sistema linguistico del futuro sarà anche il supporto di tutto, dai moderni Python / VB script per il più brutto numero di alta velocità scricchiolio.)

Come per molte cose, questo è stato prefigurato dal Lisp. Qualche tempo fa, alcuni sistemi Lisp (non si può davvero dire molte, non ci sono stati tutti che molte implementazioni Common Lisp) interpretato funzioni Lisp da loro compilazione al volo. Lisp S-espressioni (quale codice è scritto in) sono descrizioni abbastanza semplici di alberi di analisi, in modo dalla compilazione potrebbe andare abbastanza veloce. Nel frattempo, un compilatore Lisp ottimizzando potrebbe sgranocchiare codice in cui performance è stata molto importante prima del tempo.

In sostanza, i compilatori JIT ha la possibilità di profilo in realtà l'applicazione in esecuzione, e fare un po 'hinting sulla base di tali informazioni. "Offline" compilatori non saranno in grado di determinare la frequenza con un ramo salta e come spesso si cade attraverso, senza inserire codice speciale, chiedere al dev per eseguire il programma, metterlo alla prova, e ricompilare.

Perché questo tema?

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

viene convertito in qualcosa di simile:

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

E processori x86 non sarebbe prevedere un salto condizionato avanti in assenza di informazioni da parte dell'unità di branch prediction. Ciò significa che predice il codice di gestione degli errori per l'esecuzione, e il processore sta andando ad avere per sciacquare il gasdotto quando si capisce che la condizione di errore non si è verificato.

Un compilatore JIT poteva vedere che, e inserire un suggerimento per il ramo, in modo che la CPU sarebbe prevedere nella direzione corretta. Certo, i compilatori non in linea possono strutturare il codice in modo tale da evitare il mispredict, ma se mai bisogno di guardare l'assemblea, non si potrebbe piacere saltare ovunque ....

Un'altra cosa che è stato saltato in questa conversazione è che quando si JIT un pezzo di codice che può essere compilato per un posto libero in memoria. In un linguaggio come C ++, se la DLL si basa in modo tale che quel pezzo di memoria non è disponibile si dovrà passare attraverso il processo costoso di rebasing. E 'più veloce di codice JIT in un indirizzo non utilizzato poi rebase una DLL compilata in uno spazio di memoria libera. Per peggiorare le cose, una DLL ricalcolato non può più essere condivisa. (Vedi http://msdn.microsoft.com/en-us/magazine/ cc163610.aspx )

Non sono stato molto impressionato con alcune delle ottimizzazioni in C # 3.5 codice JIT. Cose semplici come po giocherellando che è necessario per la compressione sono terribilmente inefficiente (si è rifiutato di valori di cache in un registro della CPU e invece è andato a memoria per ogni operazione). Non so perché sarebbe fare questo, ma fa una grande differenza e non c'è nulla che io possa fare al riguardo.

Personalmente penso che una buona soluzione sarebbe un livello di ottimizzazione (1-100), che è possibile impostare a dire compilatore JIT quanto tempo si pensa che dovrebbe spendere l'ottimizzazione del codice. L'unica altra soluzione sarebbe un AOT (in anticipo) compilatore e poi si perde molti dei vantaggi di codice JIT.

Un sacco di persone hanno risposto forse sto skimming (forse devo avere la parte sbagliata del bastone), ma per me si tratta di due cose diverse:

Per quanto ne sappia non c'è nulla ti impedisce JIT'ing compilato C ++, ad esempio progetto di codice macchina Dynamo JIT'ed:

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

E lo ha fatto in realtà forniscono miglioramenti di velocità in determinate circostanze.

La compilazione del codice, nel senso di un compilatore C ++ significa prendere il codice scritto in un linguaggio e trasformandolo in una serie di istruzioni (o in alcuni casi un'altra lingua per poi essere compilato ancora una volta) che possono essere eseguiti da una sorta di logica dispositivo.

es. C ++ compilazione del montaggio (credo ;-) o C # compilazione di IL o Java compilazione in bytecode

JIT è un processo che avviene durante l'esecuzione. La macchina che esegue il codice analizza per vedere se può migliorarlo. Java e C # sono in grado di utilizzare sia come compilatore prepara i comandi per la VM e poi la VM ha la possibilità almeno di avere un altro andare a ottimizzazione.

Alcuni programmi non vengono compilati vengono interpretati, cioè la macchina che corre li legge il codice esatto che hai scritto. Queste macchine hanno l'oppourtunity di fare qualche JIT, ma ricordate che possono anche essere compilati staticamente, potenzialmente essere un fornitore di terze parti in modo che il progettista originale del linguaggio mai inteso.

Quindi, per rispondere alla tua domanda non credo JIT sostituirà compilatori statici. Penso che ci sarà sempre (fino a quando non v'è la programmazione almeno) un posto per prendere una rappresentazione di un programma e la conversione che in un insieme di istruzioni per una macchina di un certo tipo. (Potenzialmente ottimizzando mentre lo fa)

Tuttavia, penso che JIT può diventare una parte più grande della storia, come eseguire il Java e .NET tempo il tempo di esecuzione evolvere Sono sicuro JIT sarà ottenere le cose migliori e dato come progetto Dynamo Credo che ci sia spazio per l'hardware riprendendo JIT anche, in modo che tutto ciò che il processore non è ri-ottimizzato sulla base di ambiente di runtime.

compilatori JIT sanno più dei sistemi allora compilatori statici. Aggiunta multitheading al volo specifico per la macchina può essere un miglioramento della velocità gigantesca, una volta che farlo funzionare.

compilatori JIT, in generale, hanno un po 'di latenza di avvio in cui la prima esecuzione del programma / codice può essere molto più lento di codice precompilato. Lo svantaggio di avviamento a freddo.

Un altro grande vantaggio di compilazione JIT è che il compilatore può essere aggiornato dopo che il programma è stato costruito e acquisire nuovi trucchi compilatore senza bisogno di una nuova distribuzione programma completo.

Un vantaggio di JITing che non è ancora stato detto è che è possibile per un programma per definire un numero infinito di tipi generici. Ad esempio:

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

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

Calling Blah<Int32>.ActUpon(act) chiamerà act.Act<Int32>(). Se questo metodo restituisce true, si chiamerà Blah<Blah<Int32>>.ActUpon(act), che a sua volta chiamata act.Act<Blah<Int32>>(). Se questo restituisce vero, più chiamate saranno effettuate con un tipo ancora più-profondamente nidificato. Generazione di codice per tutti i metodi ActUpon che potrebbero essere chiamato sarebbe impossibile, ma per fortuna non è necessario. Tipi non hanno bisogno di essere generato fino a quando non vengono utilizzati. Se action<Blah<...50 levels deep...>>.Act() restituisce false, allora Blah<Blah<...50 levels deep...>>.ActUpon non chiamerà Blah<Blah<...51 levels deep...>>.ActUpon e il secondo tipo non avrà bisogno di essere creato.

Un punto non ancora menzionato che favorisce compilatori "off-line" è che tali compilatori possono utilmente indirizzare le piattaforme con piccole quantità di RAM - anche da un minimo di sedici byte. A dire il vero, tutto ciò che è anche lontanamente PC compatibile è tendono ad avere (letteralmente) milioni di volte più RAM rispetto a quello, ma penso che sarà un po 'prima che si possa trovare una macchina con molti mega di RAM che costa meno di $ 0,50 e consuma meno di un milliwatt di potenza durante il funzionamento.

Si noti che i 16 byte di RAM non è così debole come sembra, poiché i chip con tale piccola RAM Non memorizzare la codifica RAM - hanno una zona non volatile separata di memoria per contenere il codice (384 byte è il più piccolo io sappia). Non è molto, naturalmente, ma è sufficiente per consentire un processore $ 0,25 a svolgere funzioni che altrimenti richiederebbero $ 1.00 di componenti discreti.

JIT compilatori hanno più dati che possono usare per influenzare le ottimizzazioni. Naturalmente, qualcuno ha effettivamente a scrivere il codice per utilizzare tali dati, quindi non è un semplice.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top