2011-01-08 19 views
5

momento ho codice similetempo di compilazione trigonometria in C

while (very_long_loop) { 
    ... 
    y1 = getSomeValue(); 
    ... 
    x1 = y1*cos(PI/2); 
    x2 = y2*cos(SOME_CONSTANT); 
    ... 
    outputValues(x1, x2, ...); 
} 

l'ottimizzazione ovvia sarebbe quella di calcolare i coseni ahead-of-time. Potrei farlo riempiendo un array con i valori, ma mi chiedevo sarebbe possibile fare il compilatore computarli in fase di compilazione?

Edit: So che C non ha una valutazione in fase di compilazione ma speravo che ci sarebbe stato un modo strano e brutto per farlo con i macro.

+6

In realtà l'intera azienda y1 deve essere ottimizzata (da solo) poiché cos (PI/2) = 0 ... –

risposta

6

Se sei fortunato, non dovrai fare nulla: i compilatori moderni fanno propagazione costante per funzioni nella stessa unità di traduzione e funzioni intrinseche (che molto probabilmente includeranno le funzioni matematiche).

Controllare l'assemblaggio per verificare se questo è il caso per il compilatore e aumentare i livelli di ottimizzazione, se necessario.

+0

Anche tramite chiamate di funzione? –

+0

Sarei sorpreso se la propagazione costante includesse il richiamo di librerie solo nella fase di collegamento? O mi sta sfuggendo qualcosa? –

+2

GCC supporta questo dal 4.3. Vedi le note di rilascio: http://gcc.gnu.org/gcc-4.3/changes.html – BatchyX

1

No. Una tabella di ricerca precompilata sarebbe l'unico modo. Infatti, Cosine (e Sine) potrebbero essere implementati in questo modo nelle tue librerie.

Prima il profilo, Ottimizza dopo.

1

No, sfortunatamente.

Si consiglia di scrivere un piccolo programma (o script) che generi un elenco di questi valori (che è possibile quindi #include nella posizione corretta), che viene eseguito come parte del processo di compilazione.

A proposito: cos (pi/2) = 0!

0

Invece di precalcificare questi valori, è possibile utilizzare variabili globali per contenere i valori, che verrebbero calcolati una volta all'avvio del programma.

+1

non devono essere globali, solo costanti. –

1

Si presuppone che l'elaborazione di cos sia più costosa di un accesso. Forse questo non è vero per la tua architettura. Quindi dovresti fare qualche test (profilazione) - come sempre con idee di ottimizzazione.

+1

Senza hack come '-ffast-math' che non sono conformi, è praticamente impossibile che' cos() 'sia più veloce di un accesso a causa del supporto per le maiuscole e del supporto delle eccezioni 'errno'/floating point. Ovviamente, forse il compilatore potrebbe determinare che questi non sono necessari a causa dei limiti dei tuoi argomenti e utilizzare un opcode in linea fpu. –

0

No, C non ha il concetto di valutazione del tempo di compilazione di funzioni e nemmeno di costanti simboliche se sono di tipo doppio. L'unico modo per averli come operandi immediati sarebbe precomputerli e quindi definirli in macro. Questo è il modo in cui la libreria C lo fa per pi, per esempio.

+0

questa non è una funzionalità del linguaggio, ma l'implementazione; inoltre, le nuove versioni di gcc e clang faranno tali ottimizzazioni – Christoph

+0

@Christoph: la tua certezza sull'espansione del tempo di compilazione delle funzioni trigonometriche? In ogni caso, la mia tesi rimane che non ci sono costanti simboliche in C di tipo 'double'. Se li avessi come valori precalcolati, dovresti usare le macro per farvi riferimento. Questo è garantito per dare il miglior risultato su qualsiasi architettura. –

+0

sì, sono sicuro della valutazione in fase di compilazione delle funzioni trigonometriche in gcc e clang - provalo tu stesso; inoltre, non sono abbastanza sicuro di cosa intendi quando dici che non ci sono 'costanti simboliche' di tipo 'double': le espressioni costanti aritmetiche possono avere un tipo di virgola mobile; tuttavia, le enumerazioni, le etichette 'case' e ​​le condizioni del preprocessore accettano solo espressioni costanti intere; è questo che intendevi? – Christoph

0

Se si controlla il codice e il compilatore non sta sollevando i valori costanti dal ciclo, farlo da soli.

Se gli argomenti delle funzioni trigonometriche sono costanti come nel vostro codice di esempio, quindi pre-calcolateli voi stessi o rendeteli variabili statiche in modo che vengano calcolati una sola volta. Se variano da una chiamata all'altra, ma sono costanti all'interno del ciclo, spostali all'esterno del ciclo. Se variano tra le iterazioni del ciclo, una tabella di ricerca può essere più veloce, ma se ciò è accettabile, è anche possibile implementare le proprie funzioni trigonometriche che interrompono il calcolo con una precisione inferiore.

0

Sono colpito con soggezione da risposta Christoph sopra.

Quindi, in questo caso non è necessario eseguire nulla, in cui gcc ha una certa conoscenza delle funzioni matematiche.Ma se hai una funzione (magari implementata da te) che non può essere calcolata dal tuo compilatore C o se il tuo compilatore C non è così intelligente (o hai bisogno di riempire strutture dati complicate o qualche altra ragione) puoi usare un linguaggio di livello superiore agire come macroprocessore. In passato, ho usato eRuby per questo scopo, ma (ePerl dovrebbe funzionare molto bene anche ed è un altro evidente prontamente disponibili e la scelta più o meno confortevole.

È possibile specificare fare le regole per trasformare i file con estensione .eruby (o .eperl o qualsiasi altra cosa) per i file con tale estensione spogliato in modo che, ad esempio, se si scrive i file module.c.eruby o module.h.eruby poi make sa automaticamente come generare module.c o module.h, rispettivamente, e li tiene up-to-date. Nella vostra regola di make puoi facilmente aggiungere una generazione di commenti che avverte la modifica diretta del file:

Se si utilizza Windows o qualcosa di simile, non sono in grado di spiegare come aggiungere supporto per l'esecuzione automatica di questa trasformazione per il proprio IDE preferito. Ma credo che dovrebbe essere possibile, oppure potresti semplicemente eseguire make al di fuori del tuo IDE ogni volta che devi modificare quei file .eruby (o qualsiasi altra cosa).

A proposito, ho visto che con righe di codice incredibilmente piccole ho visto eLua implementato per utilizzare Lua come linguaggio macro. Ovviamente dovrebbe funzionare anche un altro linguaggio di scripting con supporto per le espressioni regolari e regole di layout flessibili (ma lo standard Python è malsuited per questo scopo a causa delle rigide regole dello spazio bianco).

Problemi correlati