XOR schneller als !=?



  • Ich benutze Duff's Device für einen byteweisen Feldvergleich. dabei habe ich festgestellt, dass ein Vergleich mit XOR

    int n = (codesize+7)>>3;
          switch(codesize&7)
          {
             case 0: do{ if(*cp++^*cq++) dif++;
             case 7:     if(*cp++^*cq++) dif++;
             case 6:     if(*cp++^*cq++) dif++;
             case 5:     if(*cp++^*cq++) dif++;
             case 4:     if(*cp++^*cq++) dif++;
             case 3:     if(*cp++^*cq++) dif++;
             case 2:     if(*cp++^*cq++) dif++;
             case 1:     if(*cp++^*cq++) dif++;
                if(dif>maxdiff) break;
             } while(--n>0);
          }
    

    etwa 20% schneller ist als das klassische !=

    int n = (codesize+7)>>3;
          switch(codesize&7)
          {
             case 0: do{ if(*cp++!=*cq++) dif++;
             case 7:     if(*cp++!=*cq++) dif++;
             case 6:     if(*cp++!=*cq++) dif++;
             case 5:     if(*cp++!=*cq++) dif++;
             case 4:     if(*cp++!=*cq++) dif++;
             case 3:     if(*cp++!=*cq++) dif++;
             case 2:     if(*cp++!=*cq++) dif++;
             case 1:     if(*cp++!=*cq++) dif++;
                if(dif>maxdiff) break;
             } while(--n>0);
          }
    

    Wieso?



  • Weils halt so ist??? Das ist CPU-abhängig, wie welche Befehle, Vergleiche, also allgemein die operationen umgesetzt sind



  • Schau einfach mal in die Intel Docs 🙂



  • das hat weder mit intel noch mit der cpu zu tun sondern eher damit, was der compiler draus macht. versuchs mal mit der 'optimize for speed' option deines compilers...



  • net schrieb:

    das hat weder mit intel noch mit der cpu zu tun sondern eher damit, was der compiler draus macht. versuchs mal mit der 'optimize for speed' option deines compilers...

    ...die Optimierung ist natürlich schon an (gcc: -O3 etc.) 😉
    Ich bin kein Assembler-Kenner, deswegen weiß ich nicht genau, was daraus gemacht wird, ich hätte aber gedacht, dass eine "non equal"-Anweisung existiert, die schneller abläuft als eine bitweises XOR mit anschließendem Vergleich des Ergebnisses auf 0.



  • versuch es mal mit

    dif+=(*cp++!=*cq++);
    

    😉



  • rapso schrieb:

    versuch es mal mit

    dif+=(*cp++!=*cq++);
    

    😉

    Schick! Das ist noch mal einen Hauch besser als die XOR-Variante. Hätt' ich nicht gedacht! 👍



  • net schrieb:

    das hat weder mit intel noch mit der cpu zu tun sondern eher damit, was der compiler draus macht. versuchs mal mit der 'optimize for speed' option deines compilers...

    Wäre aber anzunehmen, dass bei den Grundtypen der Compiler die CPU-Befehle umsetzte 🙄 Und dann isses doch wieder CPU-abhängig



  • Miq schrieb:

    rapso schrieb:

    versuch es mal mit

    dif+=(*cp++!=*cq++);
    

    😉

    Schick! Das ist noch mal einen Hauch besser als die XOR-Variante. Hätt' ich nicht gedacht! 👍

    wenn du indizierst statt zu zu increasen könnte es ebenfalls fixer werden
    ala

    dif+=(cp[0]!=cq[0]);
    

    am ende dann natürlich das nötige auf cp und cg draufaddieren

    cp+=codesize&7;
    cg+=codesize&7;
    


  • rapso schrieb:

    wenn du indizierst statt zu zu increasen könnte es ebenfalls fixer werden
    ala

    dif+=(cp[0]!=cq[0]);
    

    am ende dann natürlich das nötige auf cp und cg draufaddieren

    cp+=codesize&7;
    cg+=codesize&7;
    

    Das geht leider mit Duffs Device nicht, da das anfangs über den switch mitten in die while-Schleife springt.

    Trotzdem: danke! 😉



  • Das hat nichts mit Intel zu tun? ... egal ...
    Auf jedenfall ist ein XOR schneller als ein CMP, was der Compiler wahrscheinlich daraus macht.



  • Miq schrieb:

    rapso schrieb:

    wenn du indizierst statt zu zu increasen könnte es ebenfalls fixer werden
    ala

    dif+=(cp[0]!=cq[0]);
    

    am ende dann natürlich das nötige auf cp und cg draufaddieren

    cp+=codesize&7;
    cg+=codesize&7;
    

    Das geht leider mit Duffs Device nicht, da das anfangs über den switch mitten in die while-Schleife springt.

    Trotzdem: danke! 😉

    dann addier noch vor dem switch die codesize&7 und indiziere negativ

    dif+=(cp[-7]!=cq[-7]);
    

    und am ende der schleife jeweils +=8
    wenn der aus der schleife raus ist, dürftest du 8 drüber sein, dann wieder abziehen.
    aber an sich dürfte das laufen 🙂



  • Niemandistkeiner schrieb:

    Das hat nichts mit Intel zu tun? ... egal ...
    Auf jedenfall ist ein XOR schneller als ein CMP, was der Compiler wahrscheinlich daraus macht.

    das hängt ein wenig von der cpu ab. es gibt weit mehr als nur x86.



  • wen interessieren 5 nanosekunden wenn niemand deinen code lesen kann?



  • hoschies schrieb:

    wen interessieren 5 nanosekunden wenn niemand deinen code lesen kann?

    Weil es bei 1012 Durchläufen einen nennenswerten Unterschied macht?
    Duff's Device ist nebenbei bemerkt durchaus geläufig, und zwar seltsam, aber nicht undurchschaubar.



  • @rapso
    Ja.... es gibt weit mehr als den X86, aber ich geh davon aus, dass er es mit einem X86 Compiler kompiliert hat.



  • Frage: Warum optimiert das der Compiler (welcher?) nicht selbst?



  • Niemandistkeiner schrieb:

    @rapso
    Ja.... es gibt weit mehr als den X86, aber ich geh davon aus, dass er es mit einem X86 Compiler kompiliert hat.

    Ja, auch 🙂
    Ich entwickele parallel auf einem AthlonXP-, einem PentiumIV- und einem UltraSPARC-Rechner. Immer der selbe Sourcecode, immer gcc4 als Compiler. Das Verhalten ist zumindest ähnlich auf allen Plattformen, auch wenn es Nuancen gibt. Die IEEE-float-Implementation unter Solaris ist z.B. teilweise anders als auf den X86-Kisten. 😡


Anmelden zum Antworten