Spesso durante la scrittura del codice, mi ritrovo a utilizzare più volte un valore di una particolare chiamata di funzione. Mi sono reso conto che un'ovvia ottimizzazione sarebbe stata quella di catturare questi valori usati ripetutamente nelle variabili. Questa (pseudo codice):Come può un compilatore applicare l'eliminazione delle funzioni alle funzioni impure?
function add1(foo){ foo + 1; }
...
do_something(foo(1));
do_something_else(foo(1));
diventa:
function add1(foo){ foo + 1; }
...
bar = foo(1);
do_something(bar);
do_something_else(bar);
Tuttavia, questa operazione rende esplicito il codice meno leggibile nella mia esperienza. Supponevo che i compilatori non potessero fare questo tipo di ottimizzazione se il nostro linguaggio di scelta consente alle funzioni di avere effetti collaterali.
Recentemente ho esaminato questo e, se ho capito bene, questa ottimizzazione è/può essere fatta per le lingue in cui le funzioni devono essere pure. Questo non mi sorprende, ma presumibilmente questo può essere fatto anche per le funzioni impure. Con un paio di veloci ricerche su Google ho trovato questi frammenti: GCC 4.7 Fortran improvement
Quando si esegue front-end-ottimizzazione, l'opzione -faggressive-funzione di eliminazione consente la rimozione della funzione duplicato richiede anche per le funzioni impuri.
Compiler Optimization (Wikipedia)
Per esempio, in alcune funzioni lingue non sono autorizzati ad avere effetti collaterali. Pertanto, se un programma effettua più chiamate alla stessa funzione con gli stessi argomenti, il compilatore può immediatamente dedurre che il risultato della funzione deve essere calcolato una sola volta. Nelle lingue in cui le funzioni possono avere effetti collaterali, è possibile un'altra strategia. L'ottimizzatore può determinare quale funzione non ha effetti collaterali e limitare tali ottimizzazioni alle funzioni senza effetti collaterali. Questa ottimizzazione è possibile solo quando l'ottimizzatore ha accesso alla funzione chiamata.
Dalla mia comprensione, ciò significa che un ottimizzatore può determinare quando una funzione è o non è pura ed eseguire questa ottimizzazione quando la funzione è. Dico questo perché se una funzione produce sempre la stessa uscita quando ha lo stesso input ed è priva di effetti collaterali, soddisferebbe entrambe le condizioni per essere considerata pura.
Questi due frammenti sollevano due domande per me.
- Come può un compilatore essere in grado di eseguire in modo sicuro questa ottimizzazione se una funzione non è pura? (come in -faggressive-funzione-eliminazione)
- Come può un compilatore determinare se una funzione è pura o no? (Come nella strategia suggerita in questo articolo Wikipedia)
e infine:
- può questo tipo di ottimizzazione essere applicato a qualsiasi lingua, o solo quando si verificano determinate condizioni?
- Questa ottimizzazione è utile anche per funzioni estremamente semplici?
- Quanto sovraccarico si accumula e recupera un valore dallo stack?
Mi scuso se queste sono domande stupide o illogici. Sono solo alcune cose che sono stato curioso di recente. :)
Questo è chiamato ** eliminazione di sottoespressione comune ** http://en.wikipedia.org/wiki/Common_subexpression_elimination – leppie
La documentazione per tale opzione GNU Fortran sembra essere carente, e sospetto che generi solo codice errato se la funzione ha effetti collaterali non idempotenti. Una rapida lettura del manuale delle opzioni di generazione del codice per GNU Fortran mi ha seriamente messo in dubbio la qualità della loro implementazione - specialmente cose come mettere silenziosamente grandi variabili locali nella memoria statica ... –