Ottimizzare C++/Ottimizzazione del codice C++/Numero di istruzioni: differenze tra le versioni
Contenuto cancellato Contenuto aggiunto
m Bot: Aggiungo: en:Optimizing C++/Code optimization/Instruction count |
Riportate modifiche da en.wikibooks |
||
Riga 2:
Anche i costrutti che generano del codice espanso ''inline'' possono avere un costo significativo, in quanto tali istruzioni devono pur essere eseguite.
In questa sezione si descrivono le tecniche per ridurre il numero complessivo di istruzioni che il processore dovrà eseguire per eseguire una data operazione.▼
▲In questa sezione si descrivono le tecniche per ridurre il numero complessivo di istruzioni che il processore dovrà eseguire per
▲=== Ordine dei casi di istruzioni <code>switch</code> ===
'''Nelle istruzioni <code>switch</code>, poni i casi in ordine di probabilità decrescente.'''
Nella linea-guida "Ordine dei casi dell'istruzione <code>switch</code>" del capitolo 3.1, si consigliava già di porre prima di casi più tipici, cioè quelli che si presume siano più probabili.
Come ulteriore ottimizzazione, si
=== Parametri interi di template ===
Line 33 ⟶ 18:
Supponi che stai scrivendo la seguente funzione di libreria, in cui sia <code>x</code> che <code>y</code> non hanno un valore definito in fase di sviluppo della libreria:
<source lang=cpp>
int f1(int x, int y) { return x * y; } </source> Tale funzione può essere chiamata dal seguente codice applicativo, nel quale <code>x</code> non ha un valore costante, ma <code>y</code> è la costante 4:
<source lang=cpp>
int a = f1(b, 4); </source> Se, mentre scrivi la libreria, sai che il chiamante ti passerà sicuramente una costante intera come argomento <code>y</code>, puoi trasformare la tua funzione nel seguente template di funzione:
<source lang=cpp>
template <int Y> int f2(int x) { return x * Y; } </source> Tale funzione può essere chiamata dal seguente codice applicativo:
<source lang=cpp>
int a = f2<4>(b); </source> Tale chiamata istanzia automaticamente la seguente funzione:
<source lang=cpp>
int f2(int x) { return x * 4; } </source> Quest'ultima funzione è più veloce della precedente funzione <code>f1</code>, per i seguenti motivi:
* Viene passato un solo parametro alla funzione (<code>x</code>) invece di due (<code>x</code> e <code>y</code>).
* La
* Dato che il valore costante (4) è una potenza di due, il compilatore, invece di eseguire una moltiplicazione intera, esegue uno scorrimento di bit.
In generale, i parametri di template interi sono delle costanti per chi istanzia il template e quindi per il compilatore, e le costanti sono gestite in modo più efficiente delle variabili.
Inoltre, alcune operazioni su costanti vengono pre-calcolate in fase di compilazione.
Se invece di avere una funzione avevi già un template di funzione, basta aggiungere un ulteriore parametro a tale template.
Line 70 ⟶ 65:
class Base {
public:
virtual void f() = 0;▼
void g() { f(); }
private:
▲ virtual void f() = 0;
};
</source>
In questa classe, la funzione <code>g</code> esegue un algoritmo che
Nella terminologia dei ''design pattern'', <code>g</code> è un [[w:Template_method|template method]], ossia un algoritmo astratto con uno o più punti di personalizzazione.
Lo scopo di questa classe è consentire di scrivere il seguente codice applicativo:
<source lang=cpp>
class Derivata1: public Base {
private:
virtual void f() { ... }
};
Line 93 ⟶ 90:
template <class Derivata> class Base {
public:
void f() { static_cast<Derivata*>(this)->f(); }▼
void g() { f(); }
private:
▲ void f() { static_cast<Derivata*>(this)->f(); }
};
</source>
Line 110 ⟶ 108:
</source>
In tal modo, si ha binding statico
Tuttavia,
<source lang=cpp>
Line 121 ⟶ 119:
</source>
Con questa soluzione non
Altre limitazioni sono le seguenti:
Line 130 ⟶ 128:
=== Il pattern ''Strategy'' ===
'''Se un oggetto che implementa il ''design pattern'' [[w:Strategy pattern|''Strategy'']] (noto anche come design pattern ''Policy'') è una costante in ogni algoritmo nel codice applicativo
Supponi che stai scrivendo il seguente codice di libreria, che implementa il design pattern ''Strategy'':
Line 162 ⟶ 160:
MyStrategy s; // Oggetto che rappresenta la mia strategia.
C c; // Oggetto contenente un algoritmo con strategia personalizzabile.
c.set_strategy(s); // Assegnazione della strategia personalizzata.
c.f(); // Esecuzione dell'algoritmo con la strategia assegnata.
</source>
Line 188 ⟶ 186:
...
C<MyStrategy> c; // Oggetto con strategia
c.f(); // Esecuzione con strategia
</source>
In tal modo, si evita l'oggetto-strategia, e si ha il binding statico delle funzioni membro <code>MyStrategy::is_valid</code> e <code>MyStrategy::run</code>, cioè si evitano chiamate a funzioni <code>virtual</code>.
Tuttavia, tale soluzione non consente di decidere la strategia in fase di esecuzione, e tanto meno di cambiarla durante la vita dell'oggetto
Inoltre, il codice dell'algoritmo astratto viene duplicato ogni volta che viene personalizzato.
=== Operatori bit-a-bit ===
|