Ottimizzare C++/Ottimizzazione del codice C++/Accesso alla memoria: differenze tra le versioni
Contenuto cancellato Contenuto aggiunto
m Bot: Aggiungo: en:Optimizing C++/Code optimization/Memory access |
Riportate modifiche da en.wikibooks |
||
Riga 1:
{{Ottimizzare C++}}
L'accesso alla memoria principale da parte del processore fa implicitamente uso sia delle varie cache del processore, che
Sia le cache del processore che la memoria virtuale elaborano i dati a blocchi, per cui si velocizza il programma se si riesce a porre nello stesso blocco il codice o i dati utilizzati dalla stesso comando.▼
Il principio che i dati e il codice elaborati da un comando da un comando debbano stare vicini in memoria è detto [[w:en:Locality of reference|''località dei riferimenti'']].▼
▲Sia le cache del processore che
Qui vengono proposte delle tecniche che ottimizzano l'uso delle cache e della memoria virtuale, tramite un aumento della località dei riferimenti.▼
▲Il principio che i dati e il codice elaborati
Questo principio diventa ancora più importante per le prestazioni di applicazioni multi-threaded su sistemi multi-core, dato che se più thread in esecuzione in core distinti accedono allo stesso blocco di cache, la contesa provoca un degrado delle prestazioni.
▲
=== Avvicinare il codice ===
'''
In tal modo, il codice macchina
Un'altra conseguenza positiva è che i dati statici locali dichiarati e usati da tali funzioni avranno indirizzi vicini, e quindi maggiore località dei riferimenti dei dati.
=== Le <code>union</code> ===
'''In array o collezioni medi o grandi, usa le <code>union</code>.'''
Le <code>union</code> permettono di risparmiare memoria in strutture di tipi variabili, e quindi di renderle più compatte.
Però non usarle in oggetti piccoli o piccolissimi, in quanto non si hanno vantaggi significativi per il risparmio di memoria, e con alcuni compilatori le variabili poste
=== I ''bit-field'' ===
'''Se un oggetto medio o grande contiene
I ''bit-field'' riducono le dimensioni dell'oggetto,
Per esempio, invece della seguente struttura:
<source lang=cpp>
struct {
bool b;
unsigned short ui1, ui2, ui3; // range: [0, 1000]
};
</source>
che occupa 8 byte, puoi definire la seguente struttura:
<source lang=cpp>
struct {
unsigned b: 1;
unsigned ui1: 10, ui2: 10, ui3: 10; // range: [0, 1000]
};
</source>
che occupa solamente (1 + 10 + 10 + 10 = 31 bit, 31 <= 32) 4 byte.
Per fare un altro esempio, invece del seguente array:
<source lang=cpp>
unsigned char a[5]; // range: [-20, +20]
</source>
che occupa 5 byte, puoi definire la seguente struttura:
<source lang=cpp>
struct {
signed a1: 6, a2: 6, a3: 6, a4: 6, a5: 6; // range: [-20, +20]
};
</source>
che occupa solamente (6 + 6 + 6 + 6 + 6 = 30 bits, 30 <= 32) 4 bytes.
Tuttavia, c'è una penalità prestazionale nell'impaccare e disimpaccare i campi.
Inoltre, nell'ultimo esempio, i campi non sono più accessibile tramite un indice.
=== Codice di template non dipendente dai parametri ===
'''
Supponiamo di aver scritto il seguente codice:
Se una porzione di codice non dipende dai parametri del template, ad ogni istanziazione del template verrà generato sempre lo stesso codice.▼
Tale replicazione di codice ingrandisce inutilmente il programma.▼
<source lang=cpp>
template <typename T>
class C {
public:
C(): x_(0) { }
int f(int i) { body(); return i; }
private:
T x_;
};
</source>
Può convenire sostituire tale codice con il seguente:
<source lang=cpp>
template <typename T>
class C {
public:
C(): x_(0) { }
void f(int i) { return f_(i); }
private:
T x_;
};
void f_(int i) { body(); return i; }
</source>
Ad ogni istanziazione di un template di classe che fa uso di una funzione di quel template di classe, tutto il codice di quella funzione viene istanziato.
▲Se una
▲Tale replicazione di codice ingrandisce inutilmente il programma.
In tal caso, in primo luogo scorpora tale porzione di codice come una funzione distinta, e poi applica questa linea-guida.
|