Ottimizzare C++/Ciclo di vita dell’ottimizzazione: differenze tra le versioni
Contenuto cancellato Contenuto aggiunto
m Bot: Sostituzione automatica (-[[Categoria:Ottimizzare C++|Ottimizzare C++/ +[[Categoria:Ottimizzare C++|) |
Nessun oggetto della modifica |
||
Riga 2:
Lo sviluppo di un'applicazione efficiente procede nel seguente modo:
# '''[[w:Progettazione (ingegneria del software)|Progettazione]]''' (''design''). Dapprima si progettano gli algoritmi e le strutture dati in modo che abbiano senso per la logica applicativa, e che siano ragionevolmente efficienti, ma senza occuparsi di ottimizzarle. Dove si deve definire una struttura dati di ampio utilizzo e per la quale non è ovvio quale sia
# '''Codifica''' (''coding''). Poi si scrive il codice che implementa gli algoritmi progettati, seguendo linee-guida che permettano
# '''[[w:Collaudo del software|Collaudo funzionale]]''' (''functional testing''). Poi si
# '''[[w:Ottimizzazione (informatica)|Ottimizzazione]]''' (''tuning''). Dopo aver completato lo sviluppo di
## '''Collaudo prestazionale''' (''performance testing''). Si valuta quali comandi hanno prestazioni inadeguate, cioè quali comandi, elaborando dei dati tipici, richiedono più memoria o più tempo di quelli massimi specificati nei requisiti.
## '''''Profiling'''''. Per ogni comando avente prestazioni inadeguate, si determina, usando un profiler, quali porzioni di codice costituiscono i cosiddetti
## '''Ottimizzazione algoritmica'''. Nei colli di bottiglia, si applicano tecniche di ottimizzazione sostanzialmente indipendenti dal linguaggio di programmazione, e totalmente indipendenti dalla piattaforma. Sono le tecniche che si trovano nei testi di teoria degli algoritmi. In pratica, si cerca di ridurre il numero di istruzioni eseguite, e in particolare il numero delle chiamate a routine costose,
## '''Ottimizzazione indipendente dalla piattaforma'''. Nei colli di bottiglia, si adottano tecniche di ottimizzazione dipendenti dal linguaggio di programmazione e dalla sua libreria standard, ma indipendenti sia dalla piattaforma software che dalla piattaforma hardware. Per esempio, si usano operazioni intere invece di operazioni a virgola mobile, o si sceglie il tipo di contenitore più appropriato tra quelli disponibili nella libreria standard. Se questo rende il programma sufficientemente veloce, si termina
## '''Ottimizzazione dipendente dalla piattaforma software'''. Nei colli di bottiglia, si adottano tecniche di ottimizzazione dipendenti sia dal linguaggio di programmazione che dalla piattaforma software, ma indipendenti dalla piattaforma hardware. Per esempio, sfruttando opzioni di compilazione, direttive ''pragma'' di compilazione, estensioni al linguaggio offerte da un particolare compilatore, chiamate a librerie non-standard, chiamate dirette al sistema operativo. Se questo rende il programma sufficientemente veloce, si termina l’ottimizzazione.
## '''Ottimizzazione dipendente dalla piattaforma hardware'''. Nei colli di bottiglia si adottano tecniche di ottimizzazione dipendenti dalla piattaforma hardware, cioè o istruzioni che esistono solo su una particolare famiglia di processori, come le istruzioni in [[Assembly]], o istruzioni ad alto livello che, pur essendo eseguibili su qualunque processore, risultano vantaggiose solo su alcuni tipi di processore.
Riga 20:
Nei rari casi di software che dovrà funzionare con più compilatori e su più sistemi operativi ma su un solo tipo di processore, le fasi 4.5 e 4.6 dovrebbero essere invertite.
Questa sequenza di fasi non va affatto interpretata come una sequenza a senso unico, cioè tale per cui una volta raggiunta una fase non si torna più alla fase precedente. In realtà ogni fase può avere successo o fallire. Se ha successo, si passa alla fase successiva, se fallisce si
Inoltre, un collaudo parziale delle prestazioni deve essere eseguito dopo ogni tentativo di ottimizzazione, per verificare se il tentativo risulta utile, e, in caso affermativo, per verificare se risulta risolutivo, cioè se sono necessarie altre ottimizzazioni.
Infine, per garantire che la nuova versione ottimizzata del software non sia peggiorata né per la correttezza né per le prestazioni complessive, dopo aver completato
Questo testo approfondisce solo tre dei punti citati:
* Limitatamente
* Alcune tecniche generali relative al punto 4.3 (nel capitolo
* Limitatamente
== Notazioni terminologiche ==
In particolare, un dato associato a una variabile di un tipo fondamentale (come ''bool'', ''double'', ''unsigned long'', o un puntatore) è un oggetto, così come lo è la struttura dati associata a un'istanza di una classe. A ogni variabile è associato un oggetto, la cui lunghezza si ottiene con l'operatore del C++ <code>sizeof</code>, ma un oggetto potrebbe non avere Per esempio, un puntatore è un oggetto, ma può puntare a un altro oggetto allocato con l'operatore <code>new</code>; tale oggetto puntato non è associato a nessuna variabile.
D'altra parte, nel seguente codice, sia la variabile <code>a</code> che la variabile <code>b</code> sono associate allo stesso oggetto:
<source lang=cpp>
Si dice che un oggetto '''possiede''' un altro oggetto se la deallocazione del primo oggetto comporta la deallocazione del secondo. Per esempio, un oggetto vector non vuoto tipicamente contiene un puntatore a un oggetto array contenente gli elementi; la distruzione del vector comporta la distruzione dell'array, e quindi diciamo che tale array è posseduto dal vector.▼
int a;
int& b = a;
</source>
Gli array, le strutture, e le istanze di classi sono oggetti che (normalmente) contengono sotto-oggetti.
▲Si dice che un oggetto '''possiede''' un altro oggetto se la deallocazione del primo oggetto comporta la deallocazione del secondo. Per esempio, un oggetto <code>vector</code> non vuoto tipicamente contiene un puntatore a un oggetto array contenente gli elementi; la distruzione del <code>vector</code> comporta la distruzione
Alcune ottimizzazioni risultano applicabili solo per brevi sequenze di dati, altre per sequenze più lunghe. In seguito, si userà la seguente classificazione per le dimensioni degli oggetti:
* '''Piccolissimo''': Non oltre 8 byte. Sta in uno o due registri a 32 bit o in un registro a 64 bit.
* '''Piccolo''': Oltre 8 byte, ma non oltre 64 byte. Non sta in un registro del processore, ma sta in una linea della cache dei dati del processore, e può essere interamente indirizzato da istruzioni macchina molto compatte
* '''Medio''': Oltre 64 byte, ma non oltre 4096 byte. Non sta in una linea della cache dei dati del processore, e non può essere interamente indirizzato da istruzioni macchina compatte, ma sta nella cache dei dati di primo livello del processore, sta in una pagina di memoria virtuale, e sta in un cluster della memoria di massa.
* '''Grande''': Oltre 4096 byte. Non sta nella cache dei dati di primo livello del processore, non sta in una sola pagina di memoria virtuale, e non sta in un solo cluster della memoria di massa.
Per esempio, un array di <code>double</code> è considerato
Dato che ci sono architetture hardware molto variabili, i numeri suddetti sono solo indicativi. Tuttavia, tali numeri sono abbastanza realistici, e possono essere considerati seriamente come criteri per sviluppare del software che copra le principali architetture in modo piuttosto efficiente.
[[Categoria:Ottimizzare C++|Ciclo di vita dell'ottimizzazione]]
{{Avanzamento|
|