m(row, column) vs n(x, y)



  • Hallo,
    So weit wie ich das mitbekommen habe, macht man einen 2DArray Zugriff in dieser Reihenfolge:

    array(row, column)
    

    Und beim rüberiterieren, fängt man an mit

    for (int r = 0; r < rows, ++r)
        for (int c = 0; c < columns, ++c)
    

    Wenn man Koordinaten übergibt, schreibt man

    func(x, y);
    

    Wenn aber beide in der selben Schleife vorkommen, kann das passieren

    array(row, column) = func(column, row) // func(x, y)
    

    Das finde ich etwas irritierend. Wäre es nicht besser, wenn man den Array Zugriff in dieser Form macht?

    array(column, row)
    


  • @zeropage sagte in m(row, column) vs n(x, y):

    > array(row, column) = func(column, row) // func(x, y)
    

    Das finde ich etwas irritierend. Wäre es nicht besser, wenn man den Array Zugriff in dieser Form macht?

    array(column, row)
    

    Ich finde das gar nicht irritierend, weil ich gar nicht weiss in welche Richtungen x und y gehen. Ich vermute mal du meinst irritierend von der räumlichen Vorstellung her?

    Bei column und row ist man ja schon in dieser Vorstellung vorbelastet. Warum nennst du die nicht auch einfach x und y? Oder array_x und array_y? Das sind schliesslich nur Namen. Wichtig ist nur, dass du deine Berechnungen in der richtigen Reihenfolge machst 😉



  • Ja, ich denke schon, von der räumlichen Vorstellung her, also das horizontal column entspricht x, und vertikal row entspricht y.

    Auch wenn ich Zeilen und Spalten umbenne, kommt doch wieder das raus

    array(y, x) = func(x, y) 
    

    Wenn es so Standard ist und nur ich im Moment irritiert bin, kann ich damit leben. Ich wollte aber lieber vorher nachfragen.



  • @zeropage sagte in m(row, column) vs n(x, y):

    So weit wie ich das mitbekommen habe, macht man einen 2DArray Zugriff in dieser Reihenfolge:
    array(row, column)

    Was man allgemein wie macht, hängt davon, was denn dein "array" ist. Wenn es ein C-Style-Array ist oder ähnliches, dann liegt das einfach daran, dass mehrdimensionale Arrays in C und C++ in Row-major order gespeichert werden, siehe https://en.wikipedia.org/wiki/Row-_and_column-major_order. Wenn du Fortran benutzen würdest, wäre das andersrum, d.h. erst column, dann row.

    Wenn dein array ein eigenes Objekt ist, dann kannst du das ja so implementieren, wie du denkst - nur immer solltest du Effizienz im Hinterkopf haben - der Prozessor mag es lieber, wenn du auf die Elemente der Reihe nach zugreifst statt hin- und herzuspringen.

    Du kannst dir ja eine ColumnMajor2d-Klasse machen, die die beiden Indizes einfach umdreht...



  • @wob sagte in m(row, column) vs n(x, y):

    Wenn dein array ein eigenes Objekt ist, dann kannst du das ja so implementieren, wie du denkst - nur immer solltest du Effizienz im Hinterkopf haben - der Prozessor mag es lieber, wenn du auf die Elemente der Reihe nach zugreifst statt hin- und herzuspringen.

    Wenn man es mit der Effizienz auf die Spitze treiben will, dann kann man sich da auch nicht festlegen und die Elementanordnung dynamisch zur Laufzeit festlegen.

    Das macht es Code zwar komplexer, bietet aber auch ein paar mehr Möglichkeiten zur Optimierung. Eine Matrix zu transponieren ist da nahezu konstenlos und eine Matrix mit einer transponierten Matrix zu multiplizieren, könnte man so ziemlich cache-effizient umsetzen, da man beide linear im Speicher durchlaufen kann anstatt bei einer immer in die nächste "Zeile" springen zu müssen (und das vorherige transponieren hat man sich ja auch noch gespart).

    ... aber ich schweife mal wieder ab 😉



  • @wob sagte in m(row, column) vs n(x, y):

    Wenn es ein C-Style-Array ist oder ähnliches, dann liegt das einfach daran, dass mehrdimensionale Arrays in C und C++ in Row-major order gespeichert werden,

    Ich denke, ich lass das auch so. Weil bis auf zB Fortran macht das ja jeder so. Ist auch besser zum fremden Code übernehmen. Ja gut, danke.



  • @zeropage sagte in m(row, column) vs n(x, y):

    Ich denke, ich lass das auch so. Weil bis auf zB Fortran macht das ja jeder so. Ist auch besser zum fremden Code übernehmen. Ja gut, danke.

    Du solltest bedenken, die besten Algoritmen für Matrizen von der Hersteller selbst geliefert werden. Es gibt üblicherweise Implementationen von BLAS und LAPACK, und die sind einmal für Fortran entwickelt worden. Zum Beispiel bevor man die Matritzenmultiplikation versucht zu optimieren sollte man lieber die GEMM--Routine (C=αOp(A)Op(B)+βC)\left( C=\alpha\; Op(A)\cdot Op(B)+\beta\; C \right) nutzen. Es ist daher sinnvoll die eigene Implementation so zu entwerfen, dass man z.B. Template Spezialisierungen nutzen kann die letztlich die BLAS nutzen. Daher unbedingt vorher die Implementationen von BLAS und LAPACK anschauen.



  • richtig


Anmelden zum Antworten