Domanda

La mia funzione sarà chiamato migliaia di volte.Se voglio renderlo più veloce, se si modifica il locale funzione di variabili statiche essere di una qualche utilità?La mia logica è che, poiché le variabili statiche sono persistenti tra le chiamate di funzione sono assegnati solo la prima volta, e così, ogni chiamata successiva non allocare memoria per loro e diventano più veloci, perché l'allocazione di memoria passo è fatto.

Inoltre, se quanto sopra è vero, allora avrebbe utilizzo di variabili globali invece di parametri sia più veloce di passare informazioni alla funzione ogni volta che viene chiamato?penso che lo spazio per i parametri è destinato, inoltre, su ogni chiamata di funzione, al fine di consentire la ricorsione (ecco perché la ricorsione utilizza più memoria), ma dal momento che la mia funzione non ricorsiva, e se il mio ragionamento è corretto, allora il decollo parametri in teoria renderlo più veloce.

So che queste cose che voglio fare sono orribili abitudini di programmazione, ma per favore, dirmi se è saggio.Ho intenzione di provare comunque, ma per favore dammi il tuo parere.

È stato utile?

Soluzione

L'overhead di variabili locali è zero. Ogni volta che si chiama una funzione, si sta già configurando lo stack per i parametri, valori di ritorno, ecc Aggiunta variabili locali mezzi che si aggiunge un numero leggermente più grande al puntatore dello stack (un numero che viene calcolato in fase di compilazione) .

Inoltre, le variabili locali sono probabilmente più veloce a causa della cache località.

Se sei solo chiamando la funzione "migliaia" di volte (non milioni o miliardi), allora si dovrebbe guardare il vostro algoritmo per le opportunità di ottimizzazione dopo è stato eseguito un profiler.


Re: cache di località ( maggiori informazioni qui ): variabili globali a cui si accede frequentemente probabilmente hanno località temporale. Essi inoltre possono essere copiati in un registro durante l'esecuzione di funzione, ma sarà reintegrato nella memoria (cache), dopo una funzione restituisce (altrimenti non sarebbero accessibili a qualsiasi altra cosa, i registri non hanno indirizzi).

Le variabili locali in genere hanno entrambi località temporale e spaziale (che ottengono che in virtù di essere creati sullo stack). Inoltre, essi possono essere "allocate" direttamente ai registri e mai essere scritti nella memoria.

Altri suggerimenti

Il modo migliore per scoprirlo è quello di eseguire in realtà un profiler. Questo può essere semplice come eseguire diversi test cronometrati utilizzando entrambi i metodi e quindi mediando i risultati e confrontando, oppure si può prendere in considerazione uno strumento di profilatura conclamata che si attacca ad un procedimento e grafici fuori uso memoria nel tempo e velocità di esecuzione.

Non eseguire codice casuale a punto micro perché si ha una sensazione viscerale che sarà più veloce. I compilatori tutti hanno leggermente diverse implementazioni delle cose e ciò che è vero da un compilatore su un ambiente può essere falso su un'altra configurazione.

Per affrontare quel commento su un minor numero di parametri: il processo di funzioni "inline" rimuove essenzialmente l'overhead relativa a chiamare una funzione. Le probabilità sono una piccola funzione sarà automaticamente in-foderato dal compilatore, ma puoi suggerire una funzione di essere inline pure.

In una lingua diversa, C ++, il nuovo standard in uscita supporta l'inoltro perfetta, e semantica mossa perfetta con riferimenti rvalue che elimina la necessità per provvisori in alcuni casi che possono ridurre il costo di chiamare una funzione.

Ho il sospetto che stai prematuramente ottimizzare, tuttavia, non dovrebbe essere questo occupa di prestazioni fino a quando hai scoperto i tuoi veri colli di bottiglia.

Assolutamente no! L'unica differenza "performance" è quando le variabili vengono inizializzate

    int anint = 42;
 vs
    static int anint = 42;

Nel primo caso il numero intero verrà impostato 42 ogni volta che la funzione viene richiamata nel secondo caso ot sarà impostata su 42 quando il programma viene caricato.

Tuttavia la differenza è così banale da essere a malapena evidente. Sua un errore comune che stoccaggio deve essere assegnato per variabili "automatico" a ogni chiamata. Questo non è così C utilizza lo spazio già allocato nello stack di queste variabili.

Le variabili statiche può effettivamente rallentare se come le sue alcune ottimizzazioni aggressivi non sono possibili su variabili statiche. Inoltre, come i locali sono in una zona contigua dello stack sono più facili da memorizzare nella cache in modo efficiente.

Non c'è una risposta a questo. Esso varia con la CPU, il compilatore, il compilatore, il numero di variabili locali che hai, quello che la CPU sta facendo prima di chiamare la funzione, e molto probabilmente la fase della luna.

Si considerino due estremi; se hai solo uno o pochi variabili locali, esso / essi potrebbero facilmente essere memorizzati nei registri piuttosto che essere assegnato locazioni di memoria a tutti. Se il registro "pressione" è sufficientemente bassa che questo può accadere senza eseguire alcuna istruzione a tutti.

All'estremo opposto ci sono alcune macchine (ad esempio, mainframe IBM) che non hanno pile a tutti. In questo caso, ciò che avremmo normalmente pensiamo come stack frame sono in realtà assegnati come una lista collegata sul mucchio. Come ci si può intuire, questo può essere molto lenta.

Quando si tratta di accedere alle variabili, la situazione è un po 'simile - l'accesso a un registro macchina è abbastanza ben garantito per essere più veloce di qualsiasi allocato nella memoria può possibile sperare. OTOH, è possibile per l'accesso alle variabili nello stack di essere piuttosto lento - è normalmente richiede qualcosa come un indicizzato accesso indiretto, che (in particolare con vecchie CPU) tende ad essere piuttosto lento. OTOH, l'accesso ad un globale (quale una statica è, anche se il suo nome non è globalmente visibile) richiede tipicamente formando un indirizzo assoluto, che alcune CPU penalize certa misura pure.

Linea di fondo: anche il consiglio al profilo il codice può essere fuori luogo - la differenza può facilmente essere così piccola che anche un profiler non lo rileverà affidabile, ed il solo modo per essere sicuri è quello di esaminare il linguaggio assembly che si produce (e trascorrere un paio di anni ad imparare il linguaggio assembly abbastanza bene per sapere dire nulla quando si do sguardo esso). L'altro lato di questo è che quando hai a che fare con una differenza non si può nemmeno di misurare in modo affidabile, le probabilità che si avrà un effetto rilevante sulla velocità di codice reale è così remota che è probabilmente non vale la pena.

Sembra che la statica e non statico è stato completamente coperto, ma sul tema delle variabili globali. Spesso questi rallenterà l'esecuzione di programmi, piuttosto che per accelerarla.

Il motivo è che le variabili strettamente con ambito rendere più facile per il compilatore di ottimizzare pesantemente, se il compilatore deve guardare tutto l'applicazione per le istanze di cui una globale potrebbe essere usata allora la sua ottimizzazione non sarà così buona.

Questa è aggravata quando si introduce puntatori, supponiamo di avere il seguente codice:

int myFunction()
{
    SomeStruct *A, *B;
    FillOutSomeStruct(B);
    memcpy(A, B, sizeof(A);
    return A.result;
}

il compilatore sa che il puntatore A e B non possono mai si sovrappongono e quindi è in grado di ottimizzare la copia. Se A e B sono globali allora potrebbero eventualmente indicano sovrapposizione o memoria identici, questo significa che il mosto compilatore 'giocano scivolata' che è più lento. Il problema è generalmente chiamato 'pointer aliasing' e può verificarsi in un sacco di situazioni non solo copie di memoria.

http://en.wikipedia.org/wiki/Pointer_alias

Sì, utilizzando le variabili statiche farà una funzione di un piccolo po 'più veloce. Tuttavia, questo causerà problemi se vi capitasse di voler rendere il vostro programma multi-threaded. Poiché le variabili statiche sono condivise tra le chiamate di funzione, invocando la funzione simultaneamente in diversi thread porterebbe ad un comportamento indefinito. Multi-threading è il tipo di cosa che si consiglia di fare in futuro per davvero accelerare il vostro codice.

La maggior parte delle cose che hai menzionato sono indicati come micro-ottimizzazioni. In generale, preoccuparsi di questo genere di cose è un cattiva idea . Si rende il codice più difficile da leggere, e più difficile da mantenere. E 'anche molto probabile di introdurre bug. È probabile che ottiene più bang per il dollaro facendo ottimizzazioni a un livello superiore.

Come suggerimenti M2tM, l'esecuzione di un profiler è anche una buona idea. Scopri gprof per uno che è abbastanza facile da usare .

Si può sempre tempo di applicazione per davvero determinare ciò che è più veloce.Ecco cosa ho capito:(tutto questo dipende dall'architettura del processore, btw)

C funzioni di creare un frame dello stack, che è dove i parametri passati sono messo, e le variabili locali sono messo, così come il ritorno puntatore per cui il chiamante chiama la funzione.Non c'è la gestione della memoria allocazione qui.Di solito un semplice movimento del puntatore, e thats it.L'accesso ai dati dallo stack è anche abbastanza veloce.Le sanzioni di solito entrano in gioco quando hai a che fare con i puntatori.

Come per le variabili globali o statiche, sono la stessa cosa...dal punto di vista che si sta andando ad essere allocati nella stessa area di memoria.L'accesso a questi può utilizzare un diverso metodo di accesso di variabili locali, dipende dal compilatore.

La principale differenza tra gli scenari è ingombro di memoria, non tanto per la velocità.

Utilizzo delle variabili statiche può effettivamente rendere il codice in modo significativo più lento . Le variabili statiche devono esistere in una regione di 'dati' di memoria. Per poter utilizzare tale variabile, la funzione deve eseguire un'istruzione carico per leggere dalla memoria principale, o un'istruzione di memorizzazione per scrivere. Se quella regione non si trova nella cache, si perde molti cicli. Una variabile locale che vive nello stack sarà più sicuramente hanno un indirizzo che è nella cache, e potrebbe anche essere in un registro della CPU, non appare in memoria a tutti.

Sono d'accordo con gli altri commenti su profiling per scoprire cose del genere, ma in generale, le variabili statiche funzione devono essere più lento. Se li volete, quello che siete veramente dopo è una società globale. statica funzione di inserimento di codice / dati per verificare se la cosa è stata già che viene eseguito ogni volta che la funzione viene chiamata inizializzata.

Analisi potrebbe non vedere la differenza, scomposizione e sapendo che cosa cercare può.

Ho il sospetto che sono solo andando a ottenere una variazione per quanto pochi cicli di clock per il ciclo (in media, a seconda del compilatore, ecc).A volte il cambiamento sarà radicale miglioramento o notevolmente più lento, e che non necessariamente perché le variabili in casa si è spostato da/per la pila.Diciamo che si salva di quattro cicli di clock per ogni chiamata di funzione per 10000 chiamate di un processore a 2 ghz.Molto approssimativo calcolo:20 microsecondi salvato.20 microsecondi un sacco o un po ' di rispetto per il corrente tempo di esecuzione?

È probabile ottenere più di un miglioramento delle prestazioni, facendo tutti del vostro carattere e breve variabili in int, tra le altre cose.Micro-ottimizzazione è una buona cosa da sapere, ma prende un sacco di tempo a sperimentare, lo smontaggio, la tempistica dell'esecuzione del codice, la comprensione che un minor numero di istruzioni non significa necessariamente più veloce, per esempio.

Prendete il vostro programma specifico, smontare sia la funzione in questione e il codice che chiama.Con e senza statico.Se si acquista solo una o due istruzioni e questo è l'unico ottimizzazione si sta andando a fare, è probabilmente non vale la pena.Potrebbe non essere in grado di vedere la differenza, mentre il profiling.Cambiamenti in cui le linee di cache hit possono essere visualizzati nella profilatura prima dei cambiamenti nel codice, ad esempio.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top