Ottimizzare C++/Ottimizzazione del codice C++/Supporto run-time

Wikibooks, manuali e libri di testo liberi.
Jump to navigation Jump to search
Ottimizzare C++
modifica
CopertinaOttimizzare C++/Copertina
  1. IntroduzioneOttimizzare C++/Introduzione
  2. Ciclo di vita dell’ottimizzazioneOttimizzare C++/Ciclo di vita dell’ottimizzazione
  3. Scrivere codice C++ efficienteOttimizzare C++/Scrivere codice C++ efficiente
    1. Costrutti che migliorano le prestazioniOttimizzare C++/Scrivere codice C++ efficiente/Costrutti che migliorano le prestazioni
    2. Costrutti che peggiorano le prestazioniOttimizzare C++/Scrivere codice C++ efficiente/Costrutti che peggiorano le prestazioni
    3. Costruzioni e distruzioniOttimizzare C++/Scrivere codice C++ efficiente/Costruzioni e distruzioni
    4. Allocazioni e deallocazioniOttimizzare C++/Scrivere codice C++ efficiente/Allocazioni e deallocazioni
    5. Accesso alla memoriaOttimizzare C++/Scrivere codice C++ efficiente/Accesso alla memoria
    6. Uso dei threadOttimizzare C++/Scrivere codice C++ efficiente/Uso dei thread
  4. Tecniche generali di ottimizzazioneOttimizzare C++/Tecniche generali di ottimizzazione
    1. Input/OutputOttimizzare C++/Tecniche generali di ottimizzazione/Input/Output
    2. CachingOttimizzare C++/Tecniche generali di ottimizzazione/Caching
    3. OrdinamentoOttimizzare C++/Tecniche generali di ottimizzazione/Ordinamento
    4. Altre tecnicheOttimizzare C++/Tecniche generali di ottimizzazione/Altre tecniche
  5. Ottimizzazione del codice C++Ottimizzare C++/Ottimizzazione del codice C++
    1. Allocazione e deallocazioneOttimizzare C++/Ottimizzazione del codice C++/Allocazione e deallocazione
    2. Supporto run-timeOttimizzare C++/Ottimizzazione del codice C++/Supporto run-time
    3. Numero di istruzioniOttimizzare C++/Ottimizzazione del codice C++/Numero di istruzioni
    4. Costruzioni e distruzioniOttimizzare C++/Ottimizzazione del codice C++/Costruzioni e distruzioni
    5. PipelineOttimizzare C++/Ottimizzazione del codice C++/Pipeline
    6. Accesso alla memoriaOttimizzare C++/Ottimizzazione del codice C++/Accesso alla memoria
    7. Operazioni velociOttimizzare C++/Ottimizzazione del codice C++/Operazioni veloci

Le routine del supporto run-time del linguaggio C++ hanno ovviamente un costo significativo, in quanto altrimenti tali funzionalità sarebbero state espanse inline.

In questa sezione si presentano tecniche per evitare costrutti che comportano la chiamata implicita di costose routine del supporto run-time.

L'operatore typeid[modifica]

Invece di usare l'operatore typeid, usa una funzione virtual.

Tale operatore può richiedere un tempo superiore a quello richiesto da una semplice chiamata a funzione.

L'operatore dynamic_cast[modifica]

Invece dell'operatore dynamic_cast, usa l'operatore typeid, o, ancora meglio, una funzione virtual.

Tale operatore può richiedere un tempo notevolmente superiore a quello richiesto da una semplice chiamata a funzione, e maggiore perfino di quello richiesto dall'operatore typeid.

La specifica di eccezioni vuota[modifica]

Usa la specifica di eccezioni vuota (cioè aggiungi throw() dopo la dichiarazione) alle funzioni di cui sei certo che non solleveranno eccezioni.

Alcuni compilatori utilizzano tale informazione per ottimizzare la contabilità necessaria per gestire le eventuali eccezioni.

Il costrutto try/catch[modifica]

Sposta prima dei colli di bottiglia le istruzioni try, e dopo i colli di bottiglia le corrispondenti istruzioni catch.

In altre parole, estrai dai colli di bottiglia i blocchi try/catch.

L'esecuzione di un blocco try/catch talvolta ha costo zero, ma altre volte comporta un rallentamento. Evita di eseguire tale blocco all'interno dei colli di bottiglia.

Operazioni a virgola mobile o intere[modifica]

Se il processore target non contiene un'unità a virgola mobile, sostituisci le funzioni, costanti e variabili a virgola mobile con le corrispondenti funzioni, costanti e variabili intere; mentre se contiene un'unità a virgola mobile a precisione solamente singola, sostituisci funzioni, costanti e variabili di tipo double con le corrispondenti di tipo float.

Gli odierni processori per sistemi desktop e server contengono hardware dedicato all'aritmetica a virgola mobile, sia a precisione singola che doppia, per cui tali operazioni, sono pressoché altrettanto veloci quanto quelle su numeri interi.

Alcuni processori dedicati per sistemi embedded, invece, non contengono hardware dedicato all'aritmetica a virgola mobile, o contengono hardware in grado di gestire solo la precisione singola. Pertanto, in tali sistemi, le operazioni non disponibili in hardware vengono solamente emulate con lentissime funzioni di libreria. In tal caso, risulta molto più veloce utilizzare l'aritmetica intera, oppure, se disponibile in hardware, l'aritmetica a precisione singola.

Per gestire numeri decimali usando l'aritmetica intera si devono usare gli interi intendendoli moltiplicati per un fattore di scala. A tale scopo, ogni numero viene moltiplicato per tale fattore in fase di input e viene diviso per lo stesso fattore in fase di output, o viceversa.

Conversione da numero a stringa[modifica]

Usa funzioni ottimizzate per convertire numeri in stringa.

Le funzioni standard di conversione da numero intero a stringa e da numero a virgola mobile a stringa sono poco efficienti. Per svolgere velocemente tali operazioni, usa funzioni ottimizzate non-standard, eventualmente scritte da te.

Uso delle funzioni di cstdio[modifica]

Per eseguire operazioni di input/output, invece di usare gli stream del C++, usa le vecchie funzioni del C, dichiarate nel file di intestazione cstdio.

Le primitive di I/O del C++ sono state progettate principalmente per effettuare il controllo statico dei tipi (o type safety) e per consentire la personalizzazione per le proprie classi invece che per le prestazioni, e molte loro implementazioni risultano essere piuttosto inefficienti. In particolare, le funzioni di I/O del linguaggio C fread e fwrite sono più efficienti delle funzioni membro della classe fstream read e write.