2015-08-18 12 views
26

Nota: la presunta domanda duplicata è, penso, principalmente correlata al confronto "<" e ">", ma non al confronto "==" e quindi non risponde alla mia domanda sulle prestazioni dell'operatore "=="."==" nella matrice ordinata non è più veloce della matrice non ordinata?

Per molto tempo ho creduto che "l'elaborazione" di una matrice ordinata dovesse essere più veloce di una matrice non ordinata. In un primo momento ho pensato che l'utilizzo di "==" in array ordinato dovrebbe essere più veloce di in ordine indifferenziati perché - immagino - di come funziona la predizione dei salti:

UNSORTEDARRAY:

5 == 100 F 
43 == 100 F 
100 == 100 T 
250 == 100 F 
6 == 100 F 
(other elements to check) 

SortedArray:

5 == 100 F 
6 == 100 F 
43 == 100 F 
100 == 100 T 
(no need to check other elements, so all are F) 

quindi suppongo che SORTEDARRAY dovrebbe essere più veloce di UNSORTEDARRAY, ma oggi ho usato il codice per generare 2 array in un'intestazione da testare e la previsione delle filiali sembrava non funzionare come pensavo.

ho generato un array misti e un array ordinato di prova:

srand(time(NULL)); 
int UNSORTEDARRAY[524288]; 
int SORTEDARRAY[sizeof(UNSORTEDARRAY)/sizeof(int)]; 
for(int i=0;i<sizeof(SORTEDARRAY)/sizeof(int);i++){ 
    SORTEDARRAY[i]=UNSORTEDARRAY[i]=rand(); 
} 
sort(SORTEDARRAY,SORTEDARRAY+sizeof(SORTEDARRAY)/sizeof(int)); 
string u="const int UNSORTEDARRAY[]={"; 
string s="const int SORTEDARRAY[]={"; 
for(int i=0;i<sizeof(UNSORTEDARRAY)/sizeof(int);i++){ 
    u+=to_string(UNSORTEDARRAY[i])+","; 
    s+=to_string(SORTEDARRAY[i])+","; 
} 
u.erase(u.end()-1); 
s.erase(s.end()-1); 
u+="};\n"; 
s+="};\n"; 
ofstream out("number.h"); 
string code=u+s; 
out << code; 
out.close(); 

modo per testare, basta contare se il valore è == RAND_MAX/2 così:

#include "number.h" 
int main(){ 
int count; 
    clock_t start = clock(); 
    for(int i=0;i<sizeof(SORTEDARRAY)/sizeof(int);i++){ 
     if(SORTEDARRAY[i]==RAND_MAX/2){ 
      count++; 
     } 
    } 
    printf("%f\n",(float)(clock()-start)/CLOCKS_PER_SEC); 
} 

esecuzione 3 orari:

UNSORTEDARRAY

0.005376 
0.005239 
0.005220 

SortedArray

0.005334 
0.005120 
0.005223 

sembra una piccola differenza di prestazioni, quindi non ci credevo e poi ha cercato di cambiare "SortedArray [i] == RAND_MAX/2" a "SortedArray [i]> RAND_MAX/2" per vedere se ha fatto la differenza:

UNSORTEDARRAY

0.008407 
0.008363 
0.008606 

SortedArray

0.005306 
0.005227 
0.005146 

questa volta c'è una grande differenza.

"==" nella matrice ordinata non è più veloce della matrice non ordinata? Se sì, perché ">" nella matrice ordinata è più veloce di una matrice non ordinata, ma "==" non lo è?

+5

relativi ad una delle domande più upvoted di tutti i tempi: http://stackoverflow.com/questions/11227809/why-is- elaborazione-a-ordinata-matrice-più veloce-di-un-unsorted-array –

+0

"Credo che" l'elaborazione "di una matrice ordinata dovrebbe essere più veloce della matrice non ordinata": prova a rispondere a te stesso perché pensi che sia vero per questo algoritmo. Cioè - che tipo di lavoro e quanto ne fai per ogni caso. Potresti capire quale sia la risposta. – viraptor

+1

'string' non è un tipo standard in C, e usa l'operatore' + = 'con un operando di tipo' stringa' e l'altro 'char *' non ha senso. Sei sicuro che questo non sia un codice C++? – Sebivor

risposta

21

Una cosa che viene immediatamente in mente è l'algoritmo di previsione delle branch della CPU.

In caso di confronto >, nella matrice ordinata il comportamento di diramazione è molto coerente: in primo luogo, la condizione if è costantemente falsa, quindi è sempre true. Questo si allinea molto bene anche con la previsione di ramo più semplice.

Nella matrice non ordinata il risultato della condizione > è in modo casuale casuale, impedendo così qualsiasi previsione di ramo.

Questo è ciò che rende più veloce la versione ordinata.

In caso di confronto ==, la maggior parte delle volte la condizione è falsa e solo molto raramente è vera. Funziona bene con la previsione del ramo indipendentemente dal fatto che l'array sia ordinato o meno. I tempi sono essenzialmente gli stessi.

10

N.B. Sto facendo una risposta perché è troppo lungo per un commento.

L'effetto qui è esattamente ciò che è già spiegato in dettaglio nelle abbondanti risposte a this question. L'elaborazione di un array ordinato è stata più veloce in quel caso a causa della previsione del ramo.

Qui, il colpevole è di nuovo una previsione di ramo. Il test == è molto raramente vero, quindi la previsione del ramo funziona allo stesso modo per entrambi. Quando lo hai modificato in >, hai ottenuto il comportamento spiegato in quella domanda e per lo stesso motivo.


Morale:

credo "trattamento" un array ordinato dovrebbe essere più veloce di [un] array non ordinato.

È necessario conoscere perché. Questa non è una regola magica, e non è sempre vera.

4

Il confronto == ha meno di un ordine rispetto a >. La previsione corretta o errata di == dipende solo dal numero di valori duplicati e dalla loro distribuzione.

È possibile utilizzare perf stat per visualizzare i contatori delle prestazioni ...

[email protected] /tmp $ lz4 -d ints | perf stat ./proc-eq >/dev/null 
Successfully decoded 104824717 bytes 

Performance counter stats for './proc-eq': 

     5226.932577  task-clock (msec)   # 0.953 CPUs utilized 
       31  context-switches   # 0.006 K/sec 
       24  cpu-migrations   # 0.005 K/sec 
      3,479  page-faults    # 0.666 K/sec 
    15,763,486,767  cycles     # 3.016 GHz 
    4,238,973,549  stalled-cycles-frontend # 26.89% frontend cycles idle 
    <not supported>  stalled-cycles-backend 
    31,522,072,416  instructions    # 2.00 insns per cycle 
                # 0.13 stalled cycles per insn 
    8,515,545,178  branches     # 1629.167 M/sec 
     10,261,743  branch-misses    # 0.12% of all branches 

     5.483071045 seconds time elapsed 

[email protected] /tmp $ lz4 -d ints | sort -n | perf stat ./proc-eq >/dev/null 
Successfully decoded 104824717 bytes 

Performance counter stats for './proc-eq': 

     5536.031410  task-clock (msec)   # 0.348 CPUs utilized 
       198  context-switches   # 0.036 K/sec 
       21  cpu-migrations   # 0.004 K/sec 
      3,604  page-faults    # 0.651 K/sec 
    16,870,541,124  cycles     # 3.047 GHz 
    5,300,218,855  stalled-cycles-frontend # 31.42% frontend cycles idle 
    <not supported>  stalled-cycles-backend 
    31,526,006,118  instructions    # 1.87 insns per cycle 
                # 0.17 stalled cycles per insn 
    8,516,336,829  branches     # 1538.347 M/sec 
     10,980,571  branch-misses    # 0.13% of all branches 

[email protected] /tmp $ lz4 -d ints | perf stat ./proc-gt >/dev/null 
Successfully decoded 104824717 bytes 

Performance counter stats for './proc-gt': 

     5293.065703  task-clock (msec)   # 0.957 CPUs utilized 
       38  context-switches   # 0.007 K/sec 
       50  cpu-migrations   # 0.009 K/sec 
      3,466  page-faults    # 0.655 K/sec 
    15,972,451,322  cycles     # 3.018 GHz 
    4,350,726,606  stalled-cycles-frontend # 27.24% frontend cycles idle 
    <not supported>  stalled-cycles-backend 
    31,537,365,299  instructions    # 1.97 insns per cycle 
                # 0.14 stalled cycles per insn 
    8,515,606,640  branches     # 1608.823 M/sec 
     15,241,198  branch-misses    # 0.18% of all branches 

     5.532285374 seconds time elapsed 

[email protected] /tmp $ lz4 -d ints | sort -n | perf stat ./proc-gt >/dev/null 

     15.930144154 seconds time elapsed 

Performance counter stats for './proc-gt': 

     5203.873321  task-clock (msec)   # 0.339 CPUs utilized 
       7  context-switches   # 0.001 K/sec 
       22  cpu-migrations   # 0.004 K/sec 
      3,459  page-faults    # 0.665 K/sec 
    15,830,273,846  cycles     # 3.042 GHz 
    4,456,369,958  stalled-cycles-frontend # 28.15% frontend cycles idle 
    <not supported>  stalled-cycles-backend 
    31,540,409,224  instructions    # 1.99 insns per cycle 
                # 0.14 stalled cycles per insn 
    8,516,186,042  branches     # 1636.509 M/sec 
     10,205,058  branch-misses    # 0.12% of all branches 

     15.365528326 seconds time elapsed 
Problemi correlati