FB Code Optimierung

  • Ich such nach einer Möglichkeit folgenden Code zu beschleunigen:

    Das Resultat sollte so aussehen:

    Nach meinem Verständnis kostet die "_Circle" Funktion am meisten Zeit. Warum auch immer ist die Build-in Circle Funktion schneller (Zeile 109).

    Habt ihr noch Ideen, wie ich den Code optimieren kann, damit der Code schneller läuft?

    Soll ich ein kleines Tutorial schreiben, wie man FB benutzt? Ist fast ähnlich einfach zu bedienen wie SciTE, wenn man die erste kleine Hürde genommen hat die Umgebung einzurichten.

  • Also zuerst: Ich stecke nicht wirklich im Thema und in Freebasic schon sowieso nicht.
    Da ich das in der Shoutbox aber anscheinend losgetreten habe sollte ich mich wohl auch dazu mal äußern. ;)

    Daher erst einmal zum Verständnis - kann durchaus sein dass ich den Code falsch verstanden habe:

    • In _Circle gehst du den Kreis zeilenweise von oben nach unten durch? (cy?)
    • Dann berechnest du wo in dieser Zeile der Kreis schneidet - also das kleinste und größte x?
      Das machst du über die Sehnenlänge die sich aus dem Verhältnis aus Radius zu Sehnenabstand errechnet (also dem Höhensatz)?
    • Wenn du diese Infos hast, gehst du alle Pixel in diesem Bereich durch und färbst sie oder sowas?

    Hatte erst überlegt ob es clevere Ansätze gibt bin jetzt aber zum Schluss gekommen, dass eine Wurzel pro Zeile wirklich wenig ist und der Ansatz daher ziemlich clever.
    Was mir hingegen nicht gefällt ist die Ansprache des endgültigen Pixels - also pScrn[cyy * iW + xx].

    Dort hast du jedesmal ne Multiplikation drin nur um die Position eines Pixels im Array zu erhalten. Diese Pixel stehen im Array doch aber hintereinander!
    Daher könntest du das umschreiben, so dass der Wertebereich einfacher wird und ohne jedes mal Multiplikation auskommt. (könnte auch mit sich bringen, dass die Sachen schön im Cache bleiben) - z.B.:

    Code
    offset = cyy * iW 
    start = offset + px1
    end = offset + px2
    For xx = start To end'fill circle
        pScrn[xx] = c
    Next


    Bei den anderen Teilen des Codes sind mir beim Überfliegen noch kleine Stellen mit aufwendigen Funktionen wie z.B. Multiplikationen und Divisionen aufgefallen die man gegebenenfalls ersetzen könnte.

    Z.B.:

    • 2 * BallSize = Ballsize << 1
    • x *= -1 geht auch als x = -x (dann optimiert evtl. der Compiler) oder auch als x = 0 - x
    • c = j * 255 / BallSize innerhalb der Schleife ist Gift! Eher versuchen den Step zu berechnen und ganz einfach innerhalb der Schleife zu inkrementieren - z. B.:
    Code
    cstep = 255 / BallSize
    c = 0
    for 
        c += cstep

    Hier halt nur darauf achten, dass das Divisionsergebnis eine Dezimalzahl sein kann.

    Einmal editiert, zuletzt von AspirinJunkie (21. April 2020 um 10:16)

  • AspirinJunkie sehr gut. 4 Augen sehen mehr als 2. ;)

    In der Tat habe ich es übersehen, dass die kostenintensive Berechnung des Kreises noch optimierbar ist, wenn ich die Konstante cyy * iW innerhalb der For xx Schleife herausnehme.

    Auch 255 / BallSize ist eine Konstante die nicht in der Hauptschleife jedesmal berechnet werden muss!

    Das mit "2 * BallSize" wird nur einmal durchlaufen und macht sich nicht bemerkbar, aber wäre dies in einer permanenten Schleife, dann könnte man die Bitshift Operation wählen.

    Mit diesen zwei Optimierungen konnte ich auf meiner Kiste ca. 10 FPS herausholen! :thumbup:

    Den Richtungsvektor bei Kollision mit den Rändern von *-1 auf -vx/-vy zu stellen, macht sich nicht bemerkbar, da nur die Anzahl der Zellen aufgerufen wird, aber auch eine Optimierungsmöglichkeit.

    So sieht der Code nach dem Update aus:

    Könnt ihr auch den Unterschied auf eurem PC sehen? Auf meinem Rechner ist die FPS von ca. 30 auf ca. 40 FPS geklettert.

  • wenn ich die Konstante cyy * iW innerhalb der For xx Schleife herausnehme.

    Und doch hast du immer noch eine Addition in der Schleife die nicht sein muss.

    Schmeiß dein py doch direkt mit auf px1 und px2 drauf (außerhalb der Schleife - nicht mal im Schleifenkopf). Dann hast du im Loop nur noch pScrn[xx] = c

    Da du für einen Bereich des Arrays den genau selben Wert setzt wäre die Frage ob es hierfür auch effektivere Ansätze gibt die einen Bereich direkt abfrühstücken.
    std::fill aus C++ fällt mir da ein. Aber ob das auch was performancemäßig bringt oder nur syntactic sugar ist weiß ich nicht.

    Könnt ihr auch den Unterschied auf eurem PC sehen? Auf meinem Rechner ist die FPS von ca. 30 auf ca. 40 FPS geklettert.

    Ja kann ich - blöderweise jedoch genau andersherum. Die alte Version macht bei mir ca 40 FPS. Die neue hingegen nur 30 FPS.

    Auch wenn ich beide parallel nebeneinander laufen lasse hat die alte ~ 30 und die neue ~ 20.

    Keine Ahnung woran das liegt.

    Einmal editiert, zuletzt von AspirinJunkie (21. April 2020 um 10:52)

  • Und doch hast du immer noch eine Addition in der Schleife die nicht sein muss.

    Schmeiß dein py doch direkt mit auf px1 und px2 drauf (außerhalb der Schleife - nicht mal im Schleifenkopf). Dann hast du im Loop nur noch pScrn[xx] = c

    Ach ja, da war doch noch was.:whistling:

    Die Funktion sieht jetzt so aus

    Zwar läuft der Code jetzt noch schneller (~47 FPS), aber mit der Darstellung stimmt was nicht.

    Ja kann ich - blöderweise jedoch genau andersherum. Die alte Version macht bei mir ca 40 FPS. Die neue hingegen nur 30 FPS.

    Auch wenn ich beide parallel nebeneinander laufen lasse hat die alte ~ 30 und die neue ~ 20.

    Keine Ahnung woran das liegt.

    Das ist komisch? Die Exe ist als x64 kompiliert und sollte theoretisch durch die Maßnahmen schneller laufen...:/

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Die Bereichsüberlaufabfragen (Iif(px1...)) fehlen ja bei deiner letzten Variante.

    Das sollte jetzt in der neuen Version behoben sein.


    Das ist sehr interessant, dass nach Optimierung der Code langsamer läuft!

    Ich habe jetzt verschiedene Versionen erstellt, um den Vergleich interessanter zu machen.

    Hier das Ergebnis:

    Im Anhang die neusten Versionen.

  • Code
    Test System: Intel Core i5 M560 / Nvidia Quadro NVS 3100M / Windows10 x64 1903
    
    1) Atomic Cell World x64 (-gen gcc -Wc -Ofast).exe    21 fps
    1) Atomic Cell World x86 (-gen gcc -Wc -Ofast).exe    32 fps
    2) Atomic Cell World x64 (-gen gcc -Wc -O2).exe        22 fps
    2) Atomic Cell World x86 (-gen gcc -Wc -O2).exe        32 fps
    3) Atomic Cell World x64 (-gen gcc -O 3).exe        21 fps
    3) Atomic Cell World x86 (-gen gcc -O 3).exe        32 fps
    4) Atomic Cell World x64 (Standard).exe             11 fps
    4) Atomic Cell World x86 (Standard).exe            11 fps
  • Interessant, dass die x86 Versionen schneller als die x64 Versionen laufen. Ist auf meinem Rechner ähnlich, bis auf -gen gcc -Wc -Ofast, wo die x64 schneller läuft.

    Eine andere Sache ist, dass wenn ich die interne Circle Funktion aufrufe, dann ist die Geschwindigkeit auch höher. Ich frage mich, was an der internen Circle Funktion anders läuft, zumal sie noch diverse Checks durchführt, wie z.B. Überschreitung der Ränder, Parameter Check, usw.

    Danke allen für's Testen!:thumbup:

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Mal als Feedback weil es hier noch nicht kam: Sieht echt stark aus! :thumbup:

    Hat irgendwie was beruhigendes. Da gestern Quake angesprochen wurde - kann es sein, dass ich sowas schonmal in nem Spiel gesehen habe?
    Lavadarstellung oder sowas?

  • Auch von mir ein 'Dankeschön' für die gelungene Darstellung :thumbup:.

    Sieht wirklich cool aus. Aber ich dachte als erstes an Darmschlingen, hängt wohl mit meiner beruflichen Ausrichtung zusammen. ^^

    Ob du es glaubst oder nicht - auch ich dachte dabei an die Bilder einer Koloskopie :rofl: (Na ja, abgesehen von der grünen Farbe, das wäre wohl recht ungesund).

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

  • Krasse Fantasie Leute :rofl:

    Ich dachte eher an bewegenden Zellen eines Blattes oder so, aber ein Darm ist mir nie in den Sinn gekommen, dann eher Lava, wenn die Darstellung in rot wäre...:)

    Das wird mir wohl in die Annalen gehen...:D

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

    Einmal editiert, zuletzt von UEZ (21. April 2020 um 23:17)