2014-07-25 7 views
7

Secondo this articolo/video:doppio compilazione di codice C per diminuire il Tempi di esecuzione

GCC riconosce diverse ottimizzazioni di architettura-dipendente per aumentare la velocità di C eseguibili. Passare un eseguibile attraverso il GCC una seconda volta può spesso migliorare le prestazioni dello .

Se hai guardato il video sul collegamento, puoi vedere che questo metodo raddoppia la velocità di un eseguibile. Non sono sicuro se questo è generale.

La mia domanda è: perché succede?

Bonus: cosa succede quando ricompiliamo un programma compilato esattamente?

+13

Deve essere una bufala. Vedi come il codice contiene un 'sleep (10)'? Questa è una chiamata di sistema che mette il processo in stop per dieci secondi. Perché la "doppia compilazione" farebbe sì che il sonno dimezzasse il suo tempo? Nota come il poster non elenca i file dopo aver eseguito il primo programma. –

+0

@JoachimPileborg è per questo che sto chiedendo qui lol :) questa è la prima volta che vedo una cosa del genere –

+3

I dieci secondi che eseguono il primo programma hanno tutto il tempo per modificare la sorgente e rinominarla in "compilato" in un terminale non registrato. Ricorda che i suffissi dei nomi dei file (come '.c') sono opzionali nei sistemi POSIX (come Linux). :) –

risposta

46

Questa è una bufala.

gcc né alcun altro compilatore è in grado di leggere il codice oggetto, "compilarlo" e produrre codice oggetto più veloce.

La cosa più vicina è il feedback diretto compilation, in cui per la prima volta compila un programma con strumentazione (ad esempio gcc --fprofile-generate), eseguire tale programma, la generazione di un file di dati per la corsa (ad es foo.gcda), e quindi compilare nuovamente il programma utilizzando il stesso codice sorgente e il file di dati come input per il compilatore (es. gcc --fprofile-use). Ciò può comportare accelerazioni piuttosto modeste, in genere tra il 5% e il 10% nella mia esperienza.

Supponiamo di avere una lunga catena di 50 costrutti if … else if (che non è suscettibile di ristrutturazione come switch). Questo accade spesso nelle simulazioni Monte Carlo, per esempio. Se sei un programmatore ragionevolmente esperto, probabilmente ordinerai questi in modo che il ramo che viene preso più spesso appaia per primo. L'idea è che, in fase di esecuzione, non si perde tempo considerando 30 rami meno probabili prima di considerare il più probabile. Inoltre, tenterai di ordinare questi rami da molto probabilmente a meno probabilmente, in modo che, in media, il minor numero di test di branca venga eseguito prima che venga trovato quello giusto.

Si noti che il compilatore non ha basi per ordinare questi rami perché l'informazione che uno è più probabile di un altro semplicemente non è nel codice sorgente, quindi il meglio che si può fare è di produrre i rami nell'ordine sorgente.

Con la classica compilazione orientata al feedback, è innanzitutto necessario creare una versione strumentata dell'eseguibile che (quando lo si esegue) registra quante volte ogni ramo viene prelevato (o meno) in un file di dati. La seconda volta che compili, il compilatore ha dati empirici dal runtime (che normalmente non ha) che può essere usato per riordinare i test e inserire suggerimenti di ramo che renderanno il codice più veloce ... almeno con carichi di lavoro simili al programma di test profilato.

Sono sicuro che la compilazione moderna orientata al feedback è molto più sofisticata, ma questa è l'idea generale.

+4

Ricorda che la "compilazione diretta di feedback" è essenzialmente ciò che fa un Java "Just In Time Compiler". –

+0

Non è la stessa cosa, ma [un concetto correlato è illustrato qui bene] (http://stackoverflow.com/a/11227902/20670). –

Problemi correlati