Pointerarithmetik vs. Direktzugriff

  • Hallo Leute..

    Mich interessiert, welche Methode effizienter (im Sinne der Geschwindigkeit) ist. Die Methode mit dem Direktzugriff:

    ... oder die mit Pointerarithmetik:

    D.h. die konkrete Frage, die ich mir hier stelle ist, ob "if (*(a+x+1) < cur_a)" teurer ist als "if (my_array[z*xdim*ydim + y*xdim + x] < cur_a)"? Also auf der einen Seite [Zwei Additionen und ein Derefenzieren] und auf der anderen Seite [3 Multiplikationen und zwei Additionen]. Oder anders ausgedrueckt: dauert das Dereferenzieren eines Pointers laenger als wenn man 3 uint Werte multipliziert (wenn man die Ermittlung des Pointers a mal auszer Acht laeszt)?

    Koennt ihr mir eine Empfehlung geben, ohne, dass ich's jetzt selber testen muss?

    Danke im Voraus,
    ciao..

  • also ich bin jetzt ja dabei kein profi, aber ich würde fast sagen, dass man das allgemein gar net so sagen sagen..
    Soweit ich weiß, sind normalerweise additionen billiger als multiplikationen, allerdings kann ich mir durchaus vorstellen, dass das ganze auch auf deinen compiler ankommt, was er in welcher weise optimiert.

    außerdem würd ich bei beiden vorgehensweisen mal aufpassen, auf was du da zugreifst, weil die "Ränder des würfels" haben ja keine 26 nachbarn ;-), owa das nur nebenbei

    also ich würd ja die erste version bevorzugen, weil sie einfach viel leserlicher ist..
    aber vielleicht noch etwas.
    du führst rechnungen durch, die in der form zu oft durchgeführt werden, nämlich wird in jedem durchlauf der innersten schleife alles an multiplikationen durchgeführt, was net notwendig is...



    naja vielleicht bringt das ja was ;)

    mfg Shine

  • Zitat von \LaTeX

    D.h. die konkrete Frage, die ich mir hier stelle ist, ob "if (*(a+x+1) < cur_a)" teurer ist als "if (my_array[z*xdim*ydim + y*xdim + x] < cur_a)"? Also auf der einen Seite [Zwei Additionen und ein Derefenzieren] und auf der anderen Seite [3 Multiplikationen und zwei Additionen]. Oder anders ausgedrueckt: dauert das Dereferenzieren eines Pointers laenger als wenn man 3 uint Werte multipliziert (wenn man die Ermittlung des Pointers a mal auszer Acht laeszt)?


    Gute Compiler sollten x als Induktionsvariable erkennen und z*xdim*ydim+y*xdim als innerhalb der innersten Schleife konstanten Ausdruck und dementsprechend zweitere Form in erstere Überführen (irgendwo in den Unterlagen zur LVA Optimierende übersetzer findet sich ein schönes Beispiel dafür). Im Zweifelsfall würde ich aber Benchmarks vornehmen, nicht jeder Compiler macht auch immer das, was möglich wäre.

    PS: "dereferenzieren" ist quasi kostenlos, in der internen Darstellung der meisten Compiler ist a[i] das gleiche wie *(a+i) - sofern die Elemente des Arrays die Größe 1 haben, versteht sich.

    Why bother spending time reading up on things? Everybody's an authority, in a free land.

  • Zitat von \LaTeX

    Also auf der einen Seite [Zwei Additionen und ein Derefenzieren] und auf der anderen Seite [3 Multiplikationen und zwei Additionen].


    Naja, zwei Additionen und nix ist unoptimiert sicher billiger als zwei Additionen und irgendwas... Und den Speicherzugriff hast du bei beiden Varianten dabei.

    Zitat von jeuneS2

    in der internen Darstellung der meisten Compiler ist a[i] das gleiche wie *(a+i) - sofern die Elemente des Arrays die Größe 1 haben, versteht sich.


    Mehr noch: Laut C-Standard sind a[i] und *(a+i) völlig äquivalent. Das geht sogar so weit, daß man statt array[index] genauso auch index[array] schreiben darf, da die Addition ja kommutativ ist...
    Und die Größe der Array-Elemente ist unerheblich, da Zeiger-Offsets immer automatisch in Elementen, nicht in Bytes ö.ä. gezählt werden.

    *plantsch*

  • Zitat von Plantschkuh!

    Mehr noch: Laut C-Standard sind a[i] und *(a+i) völlig äquivalent. Das geht sogar so weit, daß man statt array[index] genauso auch index[array] schreiben darf, da die Addition ja kommutativ ist...

    hmmm...

    Code
    main() {
            char str[] = "hallo!";
            printf("%c\n",str[3]);
            printf("%c\n",3[str]);
    }

    funktioniert tatsächlich! Selbst nach 7 Jahren C-Erfahrung kann man trotzdem noch was dazulernen... Danke Plantschkuh! :D

    Dieses Wissen hilft mir aber wohl eher für den C-Obfuscation-Wettbewerb als anderswo... Die komplizierteste Art, 1+1 zu rechnen: &1[(char*)1] :D

    [font=verdana,sans-serif]"An über-programmer is likely to be someone who stares quietly into space and then says 'Hmm. I think I've seen something like this before.'" -- John D. Cock[/font]

    opentu.net - freier, unzensierter Informationsaustausch via IRC-Channel!
    Hilfe und Support in Studienangelegenheiten, gemütliches Beisammensein, von und mit Leuten aus dem Informatik-Forum!

  • Zitat von Shine


    außerdem würd ich bei beiden vorgehensweisen mal aufpassen, auf was du da zugreifst, weil die "Ränder des würfels" haben ja keine 26 nachbarn ;-), owa das nur nebenbei

    Klar, das war auch durch '...' im Code repraesentiert :) Die Raender musst ja eh' fuer beide Varianten ueberpruefen.

    Zitat von Shine

    du führst rechnungen durch, die in der form zu oft durchgeführt werden, nämlich wird in jedem durchlauf der innersten schleife alles an multiplikationen durchgeführt, was net notwendig is...

    naja vielleicht bringt das ja was ;)

    Da hast' Recht, danke fuer'n Hinweis.

    Zitat von Plantschkuh!

    Naja, zwei Additionen und nix ist unoptimiert sicher billiger als zwei Additionen und irgendwas... Und den Speicherzugriff hast du bei beiden Varianten dabei.

    Cool, d.h. der Dereference Operator ist zur Laufzeit in diesem Fall "for free"?

    Danke nochmals fuer euere Beitraege. Jetzt ist einiges klarer.
    ciao

  • Zitat von \LaTeX

    Cool, d.h. der Dereference Operator ist zur Laufzeit in diesem Fall "for free"?


    Nein, Speicherzugriffe sind nicht for free, sie sind sogar vergleichsweise teuer. Ich wollte nur ausdrücken, daß * und [] beides Operatoren zur Dereferenzierung sind, also hast du bei beiden die gleichen Kosten für den Speicherzugriff.

    *plantsch*

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!