2011-01-31 11 views
6

I compilatori C/C++ ottimizzano le funzioni a livello singolo con parametri costanti (noti al momento della compilazione) solo quando si utilizzano -Os, -O1 e -O2. Non ottimizzano tutti i livelli. Solo -O3 può farlo. gcc è WinAVR 4.3.3 che non supporta l'attributo "ottimizzare".c/C++ ottimizzazione per variabile costante nelle funzioni di chiamata

void inner(double value) 
{ 
    //operations using value 
    //... 
} 

void outer(double value) 
{ 
    //few operations using value 
    //... 
    inner(value); 
} 

int main() 
{ 
    inner(1); //optimize 
    outer(1); //only optimize by using -O3 
} 

Quali sono le possibili soluzioni oltre ai seguenti?

  1. -O3 programma di attesa o di file (uso improprio farà saltare in aria la dimensione)
  2. attribuiscono ottimizzare -O3 per le funzioni (4.3.3 non supporta)
  3. macro (soggetto a errori)

Aggiornamento:

//inner function 
static inline void _delay_us(double __us) __attribute__((always_inline)); 
//outer function 
void f(double); 
inline f1(double); 
static inline f2(double); 
static f3(double); 

f1 è ottimizzato b ut avvertimento '_delay_us' è statico ma viene utilizzato nella funzione inline 'f1' che non è statica a causa di problemi di funzione statica. Altri non sono ottimizzati.


Soluzione:

static inline void outer(double) __attribute__((always_inline)); 

Inline è la chiave. La mia funzione esterna è troppo grande per essere in linea. L'attributo always_inline impone che la funzione sia in linea. Ciò consente al compilatore di ottimizzare la funzione con un costo di compilazione inferiore rispetto al tentativo di calcolare l'ottimizzazione. -O3 è abbastanza intelligente da fare l'ottimizzazione ma non -Os. -Os potrebbe richiedere alcune opzioni del compilatore. (La parola chiave static è necessaria perché la funzione interna è anche statica in linea.)

+0

Hm, non sono sicuro di capire perché questo è un problema. Se vuoi che il compilatore ottimizzi, diglielo. Se temi che '-O3' (o qualsiasi altro livello) faccia esplodere la dimensione del tuo codice,' -Os' è solo la strada da percorrere. –

+0

Il codice viene utilizzato nei microcontrollori a 8 bit che non hanno l'ALU in virgola mobile hardware. -O3 in effetti danno una dimensione del codice più piccola di -Os in questa funzione, 4k vs 400 – keithyip

risposta

3

Un po 'simile all'opzione macro (3), ma senza gli svantaggi di una macro, è possibile eseguire specifiche funzioni inline, che in genere determinano le ottimizzazioni costanti desiderate. Ovviamente questo aiuta solo se stai chiamando le funzioni rilevanti da un posto (o da pochi posti), altrimenti il ​​codice bloat diventa un problema.

Si noti che gcc ha una disposizione per forzare le funzioni inline specifiche a essere sempre in linea (anziché lasciare questo a discrezione del compilatore): __attribute__ ((always_inline)). Altri compilatori avranno in genere un meccanismo simile, sebbene possa trattarsi di un commutatore a riga di comando o di un pragma.

+0

Nota che (standard C++) 'inline' è solo un suggerimento per il compilatore. Il compilatore può ignorare tali suggerimenti se il compilatore determina che l'inlining non vale la pena o non è necessario. Come viene presa questa decisione dipende dall'implementazione. –

+0

@In silico: true, ma gcc ti permette di forzare le funzioni inline a essere inline: '__atttribute__ ((always_inline))' –

+0

Ho perso per provare in linea! Ho aggiornato il post. – keithyip

1

In GCC almeno, le flag -O attivano solo un intero carico di altri flag, vedere ad es. http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html. Potresti semplicemente abilitare quelli a cui sei interessato, anche se questo è generalmente scoraggiato.

Si noti che non sono sicuro che il comportamento di ad es. GCC a -O2 e -O3 è necessariamente un indicatore di ciò che farà un compilatore completamente diverso.

+0

Le opzioni individuali sono molto utili nella programmazione del microcontrollore. – keithyip

+0

@nothing: In effetti, anche se spesso mi porta a ingegnerizzare in un angolo, nella mia esperienza! –

0

Come punto generale, se si aumentano le informazioni fornite al compilatore, potrebbe essere possibile eseguire un'ottimizzazione migliore.

Per esempio, supponendo che quelle sono le uniche chiamate inner e outer poi li si potrebbe dichiarare come static per limitarne la portata e consentire il compilatore maggiore flessibilità nel modo in cui li ottimizza.

A seconda del contenuto effettivo delle funzioni si potrebbe potrebbe anche dichiarare i loro parametri come const che consente al compilatore di sapere subito che non possono essere modificate senza dover analizzare il codice

static void inner(const double value) 
{ 
    //operations using value 
} 

static void outer(const double value) 
{ 
    //few operations using value 
    //... 
    inner(value); 
} 
+0

non aiutano molto. La mia funzione esterna è troppo costosa per ottimizzare automaticamente senza forzare in linea. – keithyip

0

Come di introdurre un funzione 'outerFast', definita nel proprio cpp, comprese le definizioni di inner e outer e compilando solo quel file con -O3?

Ha i suoi svantaggi, però.

+0

Sto scrivendo alcune librerie. La configurazione complessa non è facile da usare per gli utenti, ma il controllo di ottimizzazione fine per i singoli file è molto utile in produzione. – keithyip

Problemi correlati