2015-08-18 9 views
26

Hinweis: die angebliche doppelte Frage ist, denke ich, meist bezogen auf "<" und ">" Vergleich, aber nicht "==" Vergleich und daher nicht meine Frage nach der Leistung des "==" -Operators.Ist "==" im sortierten Array nicht schneller als unsortiertes Array?

Ich habe lange geglaubt, dass die "Verarbeitung" eines sortierten Arrays schneller sein sollte als ein unsortiertes Array. Zuerst dachte ich, "==" in sortierten Array sollte schneller sein als in unsortierten Array, weil - ich denke - wie Verzweigungsvorhersage arbeitet:

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) 

Also ich denke, SORTEDARRAY sollte schneller sein als UNSORTEDARRAY, aber heute habe ich den Code verwendet, um 2 Arrays in einem Header zu testen, und Zweig Vorhersage schien nicht zu funktionieren, wie ich dachte.

I eine unsortierte Array und ein sortiertes Array zu Test generiert:

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(); 

so zu testen, zählen nur, wenn der Wert == RAND_MAX/2 ist wie folgt:

#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); 
} 

Lauf 3 Zeiten:

UNSORTEDARRAY

0.005376 
0.005239 
0.005220 

SORTEDARRAY

0.005334 
0.005120 
0.005223 

scheint es einen kleinen Unterschied in der Leistung, so dass ich es nicht glauben, und dann versucht, ändern "SORTEDARRAY [i] == RAND_MAX/2" bis "SORTEDARRAY [i]> RAND_MAX/2" um zu sehen, ob es einen Unterschied gemacht:

UNSORTEDARRAY

0.008407 
0.008363 
0.008606 

SORTEDARRAY

0.005306 
0.005227 
0.005146 

Diesmal gibt es einen großen Unterschied.

Ist "==" im sortierten Array nicht schneller als unsortiertes Array? Wenn ja, warum ist ">" im sortierten Array schneller als ein unsortiertes Array, aber "==" nicht?

+5

Bezug zu einem der upvoted Fragen aller Zeiten: http://stackoverflow.com/questions/11227809/why-is- processing-a-sorted-array-schneller-als-unsortiertes-array –

+0

"Ich glaube," Verarbeitung "sortierte Array sollte schneller sein als unsortierte Array": versuchen Sie selbst zu beantworten, warum Sie denken, dass das für diesen Algorithmus wahr ist. Das ist - welche Art von Arbeit und wie viel davon Sie für jeden Fall tun. Sie können erkennen, was die Antwort ist. – viraptor

+1

'string' ist kein Standardtyp in C und die Verwendung des' + = 'Operators mit einem Operanden vom Typ' string' und dem anderen 'char *' macht keinen Sinn. Sind Sie sicher, dass dies kein C++ - Code ist? – Sebivor

Antwort

21

Eine Sache, die sofort in den Sinn kommt, ist der Verzweigungsvorhersagealgorithmus der CPU.

Im Fall von > Vergleich, in sortierten Array ist das Verzweigungsverhalten sehr konsistent: erstens ist die if Bedingung konsequent falsch, dann ist es konsistent wahr. Dies stimmt sehr gut mit der einfachsten Verzweigungsvorhersage überein.

In einem unsortierten Array ist das Ergebnis der > Bedingung im Wesentlichen zufällig, wodurch jede Verzweigungsvorhersage vereitelt wird.

Dies macht die sortierte Version schneller.

Im Fall von == Vergleich ist die Bedingung die meiste Zeit falsch und nur sehr selten ist es wahr. Dies funktioniert gut mit der Verzweigungsvorhersage unabhängig davon, ob das Array sortiert ist oder nicht. Die Zeiten sind im Wesentlichen gleich.

10

N.B. Ich mache das eine Antwort, da es für einen Kommentar zu lang ist.

Die Wirkung hier ist genau das, was bereits ausführlich in den zahlreichen Antworten auf this question erklärt wurde. Die Verarbeitung eines sortierten Arrays war in diesem Fall wegen der Verzweigungsvorhersage schneller.

Hier ist der Täter wieder Verzweigung Vorhersage. Der == Test ist sehr selten richtig, so dass die Verzweigungsvorhersage für beide gleichermaßen funktioniert. Wenn Sie es zu > änderten, dann haben Sie das Verhalten, das in dieser Frage erklärt wird, und aus dem gleichen Grund.


Moral:

Ich glaube, "Verarbeitung" ein sortiertes Array als schneller sein sollte, [ein] unsortierten Array.

Sie müssen wissen warum. Dies ist keine magische Regel, und es ist nicht immer wahr.

4

Der Vergleich == hat weniger eine Beziehung zur Bestellung als > tut. Die korrekte oder falsche Vorhersage von == hängt nur von der Anzahl der doppelten Werte und deren Verteilung ab.

Sie perf stat verwenden können, um die Leistungsindikatoren zu sehen ...

[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