2013-04-28 45 views
6

Sto provando a ripetere un blocco di codice, senza utilizzare una condizione, ma ancora solo ripetendolo un numero specifico di volte.Ripetere un blocco di codice un numero fisso di volte

In sostanza, qualcosa di simile:

repeat(50) 
{ 
    //Do stuff here. 
} 

C'è un modo per fare questo? Altro che copiare e incollare 50 volte?

Lo sto facendo perché ho pensato che se so quante volte voglio ripetere qualcosa, sarebbe più veloce che controllare ogni volta una condizione. È esatto? O controllerei ancora quante volte è stato ripetuto?

Fondamentalmente, è più veloce?

+0

Stai cercando solo una ripetizione? come in 50 esecuzioni del codice sans- * any * conditionals? – WhozCraig

+1

Per quanto ne so, il compilatore spesso ottimizza un ciclo for utilizzando una dimensione letterale (non basata su variabili) nello stesso codice risultante di aver scritto quel codice x volte. Quindi 'repeat (50)' sarebbe uguale a 'for (char i = 0; i <50; i ++)' (ho usato char causa nel caso in cui non sia ottimizzato out non assegnerà 4 byte per il 'int' ma solo 1 per il 'char'). –

+0

@MrUniverse Grande, grazie, proprio quello di cui avevo bisogno. – Serdnad

risposta

10

I tentativi di ottimizzare il loop utilizzando un costrutto (incluso il taglio manuale di & che incolla il codice) per ottimizzare la velocità di esecuzione del loop sono sconsigliati. Non farlo; probabilmente "annullerebbe" la velocità di esecuzione.

In qualsiasi implementazione C++ che abbia mai incontrato (MSVC 6.0, 2003, 2005, 2010, GCC varie versioni, Diab varie versioni), c'è assolutamente zero, mi dispiace non averlo sottolineato abbastanza, ZERO, tempo richiesto con l'allocazione di una variabile di conteggio del ciclo, supponendo che siano state allocate altre variabili per la funzione in cui è allocata la variabile di conteggio del ciclo. Per un ciclo semplice che non fa chiamate di funzioni, la variabile di conteggio del ciclo potrebbe non essere mai nemmeno uscita in memoria; può essere tenuto interamente in un unico registro CPU per tutta la sua durata. Anche se è immagazzinato in memoria, sarebbe sullo stack di runtime, e lo spazio per esso (e qualsiasi altra variabile locale) verrebbe rivendicato tutto in una volta in un'unica operazione, che non richiede più o meno tempo a seconda del numero di variabili allocate nello stack. Le variabili locali come la variabile del ciclo di loop sono allocate nello stack e le allocazioni di stack sono ECONOMICHE A BUON MERCATO ECONOMICO, a differenza delle allocazioni di heap.

allocazione

Esempio contatore di ciclo variabile in pila:

for (int i=0; i<50; ++i) { 
    .... 
} 

altro esempio circuito contatore allocazione variabile in pila:

int i = 0; 
for (; i<50; ++i) { 
    .... 
} 

variabile Esempio contatore di ciclo assegnato in mucchio (non fare questo: è stupido):

int* ip = new int; 
for (*ip=0; *ip<50; ++(*ip)) { 
    .... 
} 
delete ip; 

Ora per affrontare il problema di atte per ottimizzare il ciclo copiando manualmente la copia & invece di utilizzare un contatore &:

Quello che stai pensando di fare è una forma manuale di srotolamento del ciclo. Lo srotolamento del ciclo è un'ottimizzazione che i compilatori utilizzano a volte per ridurre l'overhead coinvolto in un ciclo. I compilatori possono farlo solo se il numero di iterazioni del ciclo può essere conosciuto in fase di compilazione (cioè il numero di iterazioni è una costante, anche se la costante implica il calcolo basato su altre costanti). In alcuni casi, il compilatore può determinare che vale la pena di srotolare il ciclo, ma spesso non lo srotolerà completamente. Ad esempio, nel tuo esempio, il compilatore può determinare che sarebbe un vantaggio di velocità srotolare il ciclo da 50 iterazioni a solo 10 iterazioni con 5 copie del corpo del ciclo. La variabile del ciclo sarebbe ancora lì, ma invece di fare 50 confronti del contatore del ciclo, ora il codice deve fare il confronto solo 10 volte. È un compromesso, perché le 5 copie del corpo del ciclo consumano 5 volte più spazio nella cache, il che significa che il caricamento di quelle copie aggiuntive delle stesse istruzioni costringe la cache a sfrattare (buttare via) molte istruzioni che sono già in la cache e che potresti voler rimanere nella cache. Inoltre, il caricamento di quelle 4 copie extra delle istruzioni del corpo del loop dalla memoria principale richiede molto, molto più tempo del semplice prelievo delle istruzioni già caricate dalla cache nel caso in cui il loop non sia srotolato affatto.

Quindi, tutto sommato, è spesso più vantaggioso utilizzare solo una copia del corpo del loop e andare avanti e lasciare la logica del loop in posizione. (Ad esempio, non eseguire alcun ciclo di srotolamento.)

+0

Il secondo ciclo non verrà mai eseguito. Immagino tu intenda "int i = 0;"? – Aleph

+0

@AnotherTest - Fai il caso delle recensioni peer di codice! Grazie. – phonetagger

-1

Devo dire che il più grande aumento di velocità sarebbe il fatto che non si sta allocando una variabile di iterazione, ma ciò che si è richiesto avrebbe inevitabilmente bisogno di verificare una condizione. in sostanza quello che hai lì è il seguente.

int i = 0; 
for(; i< 50; i++) 
{ 
    Do Something. 
} 

Il motivo che ho spostato all'esterno del ciclo for è dichiarare può essere qualsiasi variabile inizializzata prima del ciclo. È percisely la stessa cosa,

for(int i =0; i< 50; i++) 
{ 
} 
+0

Perché non 'for (int i = 0; i <...)'? –

+0

è esattamente come sopra? appena spostato l'inizializzazione dal ciclo for. Solo affermando che potrebbe essere una variabile creata in qualsiasi punto prima del ciclo. – Nomad101

+0

La variabile non viene allocata ogni volta comunque, questo codice equivale a dichiarare 'i' all'interno del ciclo. –

1

Sarebbe del tutto possibile avere una repeat(x) come parte del linguaggio, ma non c'è una cosa del genere per qualche ragione - la progettazione di C e C++ fa un po ' seguire ciò che i processori possono fare, e non ho familiarità con un singolo processore (ho lavorato con circa 10 diverse architetture di processore) che possono fare un "loop tante volte" senza una sorta di "verifica se abbiamo raggiunto il numero ".

Quindi, dovrai scrivere un codice che controlla quante volte hai ripetuto qualcosa (o quante volte ci sono ancora da fare) c'è un'istruzione x86 chiamata "loop" che fa proprio questo: conta giù, e se il contatore non è zero, salta all'inizio del ciclo).

Se il compilatore desidera "srotolare" un ciclo perché ha un numero costante di iterazioni e decide "srotolare questo è più veloce" [i compilatori decidono sempre questo tipo di cose e spesso lo fanno correttamente] , quindi il compilatore potrebbe farlo. Ma devi ancora scrivere il codice che "controlla".

+0

Ok, grazie per le cose del processore, è stato interessante. Completamente dimenticato dell'ottimizzazione del compilatore. – Serdnad

Problemi correlati