Optimierung meines Mandelbrot-Explorers



  • @RudiMBM sagte in Optimierung meines Mandelbrot-Explorers:

    @hustbaer Ja, in beiden Vers. wird nur das quadrat von z verglichen. Soll ja optimiert ablaufen.

    Dann probier mal "Chebyshev distance" oder "Manhattan distance". Das sollte nochmal einiges bringen.

    "Chebyshev distance" ist einfach nur max(abs(x2-x1), abs(y2-y1)) und "Manhattan distance" ist abs(x2-x1) + abs(y2-y1). Bzw. halt r und i statt x und y in diesem Fall.

    Für die Entscheidung ob der Fehler klein genug ist, sollten beide ausreichend sein. (Bei der "Chebyshev distance" müsstest du noch Epsilon halbieren damit der Vergleich fair ist.)



  • @hustbaer Wozu das? In der Iter-Formel fällt sowieso real² und Imag² an, da brauch ich nur 1 Addition für Pytagoras abs(z)². Allerdings möchte ich erwähnen, dass ich Epslilon bereits als squared ein- und angegeben habe. Im Test war das 1e-16. Unsquared wären das dann 1e-8.



  • @RudiMBM sagte in Optimierung meines Mandelbrot-Explorers:

    @hustbaer Wozu das? In der Iter-Formel fällt sowieso real² und Imag² an, da brauch ich nur 1 Addition für Pytagoras abs(z)².

    Ähm. Ich versteh' jetzt mal nicht wie das gehen soll. Wo sollen in der Iteration (z_r - zref_r)² und (z_i - zref_i)² anfallen?

    EDIT: Also ich rede von dieser Zeile da: if (abs(z - zref) < Epsilon)



  • @hustbaer sagte in Optimierung meines Mandelbrot-Explorers:

    Also ich rede von dieser Zeile da: if (abs(z - zref) < Epsilon)

    dann mach doch mal

    if ( abs( z²-zref²) < Epsilon²) 
    

    dann brauchste nicht vorher Wurzelziehen. Und geht doch, oder?



  • @RudiMBM
    Geht schon, ist bloss nicht das selbe.
    (a-b)² = a² - 2ab + b² und nicht a² - b²

    Damit bekommst du einerseits zu grosse bzw. zu kleine Fehlerwerte (je nachdem ob du ausserhalb oder innerhalb des Einheitskreises bist). Beispiel: (2-3)² ist 1 aber |2²-3²| ist 5*.

    Und andrerseits bekommst du false positives.

    Also ich persönlich würde da wirklich einfach eine andere Distanz-Metrik verwenden.

    *: Ja, ich weiss dass der Bereich ausserhalb der Mandelbrotmenge liegt. War nur ein Beispiel, im "relevanten" Bereich werden die Abweichungen geringer sein. Trotzdem sind sie da, und variieren vor allem je nachdem wie weit man vom Einheitskreis entfernt ist. Und speziell im Bereich r=0.25, der ja auch halbwegs interessant sein sollte, sind die Abweichungen dann schon nicht mehr so klein.



  • Ihr solltet auch Bedenken, das der PC nie eine wirklichen Reihe berechnet. Sondern nur eine Näherung, die wegen der chaotischen Natur immer weiter abweicht, von der richtigen Reihe. Ist z aus zwei floats, gibts grad mal 2^63 Kombinationen. Nochmal weniger, wenn man den Exponent beschränkt. Man sollte also echt mal einfach alle z markiert, die in Zyklenlängen über x vorkommen, bzw. einfach jedes z nach x Gliedern der Zyklen. Dann hat man eine Obergrenze von Rechenschritten, mit dem für jedes z die Lösung bestimmt wird.



  • @TGGC z ist komplex, also bei double wären das dann schon 2^126. Und @RudiMBM (bzw. sein Programm) rechnet mit 360 Bit Fixkommazahlen. Also 2^720. Hui 🙂



  • @TGGC sagte:

    Ihr solltet auch Bedenken, das der PC nie eine wirklichen Reihe berechnet. Sondern nur eine Näherung, die wegen der chaotischen Natur immer weiter abweicht, ....

    Das ist ein weitverbreiteter Irrtum, dass in der Computer-MBM-Iterations-Folge das Chaos beteiligt ist. Die Abweichungen entstehen durch die Begrenzung der Nachkommastellen. Bei den Multiplikationen werden hinten signifikante Ziffern nach rechts rausgeschoben. Bei sqrt(x) zB. werden wieder Nachkommastellen von rechts hereingeholt, und das sind in der Regel Nullen. Bei sqrt(x²) bleibt also nur die halbe Genauigkeit übrig. (Nicht in der reinen Mathematik) Ab diesen Iterationsschritt ist die Folge verfälscht, oder man kann sagen es ist eine Andere. Das wahre Chaos kann nur in einem analogen System erfolgen, Da gibt es keine Nachkommastellen, oder je nachdem unendlich viele.



  • @hustbaer sagte:

    Geht schon, ist bloss nicht das selbe.
    (a-b)² = a² - 2ab + b² und nicht a² - b²

    Ich habe in in diesem Punkt wohl sehr ungeschick formuliert.
    In der Iterationsschleife wird programmiert um den neuen Betrag(z) zu erhalten:

    remain_iter = max_iter
    xx = x*x
    yy = y*y
    xy = x*y
    betrag_z² = xx + yy
    WHILE (betrag_z² <= max_betrag_z²) AND (remain_iter > 0)
      remain_iter = remain_iter - 1
      x  = xx - yy + cx
      y  = xy + xy + cy
      xx = x*x
      yy = y*y
      xy = x*y
      betrag_z² = xx + yy
     // hier der break-Test
    END
    

    Aus betrag_z² wird letztlich betrag_zref² ermittelt, und wenn ich beide Quadrate subtrahiere (großes - kleines), bleibt eine Restfläche übrig. Wenn die kleiner ist als Epsilon² bin ich fertig.



  • @RudiMBM
    Also anders gesagt: du nimmst in Kauf dass dein "effektives" Epsilon abhängig vom Betrag von z schwankt. Korrekt?

    Dann kann mMn. der Unterschied nur mehr sein dass deine "Variante 1" die Konvergenz mit weniger Zyklen erkennt als die auf meinem Vorschlag basierende "Variante 2". Denn wenn du dir die Anzahl an Operationen ansiehst die du hier pro Schritt benötigst, also speziell die Multiplikationen, dann können eine Subtraktion und ein Vergleich das nicht so drastisch langsamer machen.

    BTW: Hast du mal probiert was passiert wenn du beide Abbruchbedingungen kombinierst? Also eine Variante "1&2"?



  • @hustbaer sagte in Optimierung meines Mandelbrot-Explorers:

    Also anders gesagt: du nimmst in Kauf dass dein "effektives" Epsilon abhängig vom Betrag von z schwankt. Korrekt?

    Wieso soll es schwanken? Epsilon und Epsilon² ist über alle Bildpunkte und Zwischeniterationsergenisse eine Konstande. Ich hab es ja schon mal erwähnt: Die Hüllkurve. zB. c = (0.5,0.5) das ist ein Grundzyclus. Im Verlauf der Iteration werden sich die Iterationsergenisse einem bestimmt Punkt z annähern. Dadurch werden sich der Betrag(z von i) und der Betrag(z von i-x) annähern. Unterschreitet die Differenz Epsilon dann.... Erstaunlicher Weise funktioniert das auch bei allen anderen Zyclen. (Aber die Begründung dafür würde einen neuen Thread benötigen)

    "Variante 1" die Konvergenz mit weniger Zyclen erkennt als die auf meinem Vorschlag basierende "Variante 2"

    Ich bin nicht sicher wieviele Iterationen jeweils nötig sind, vielleich sogar mehr, aber es ist sicher, dass in Vers.1 viel weniger Codezeilen pro Iteration ausgeführt werden.

    zu BTW: ich hab keinen Plan dazu.

    Jetzt sollte aber noch der Begriff "Zyclus" vs. Iteration geklärt werden, wie mir auffällt. Ich glaube wir sprechen da von verschiedenen Parametern. c = (-1|0) wäre ein 2er Zyclus.



  • @RudiMBM

    Wieso soll es schwanken? Epsilon und Epsilon² ist über alle Bildpunkte und Zwischeniterationsergenisse eine Konstande.

    Ja, sorry, ich hab das wohl etwas zu undeutlich formuliert. Mit "effektives" Epsilon meine ich die Distanz (|a-b|) zwischen den beiden Punkten. Da du eine andere Formel für das Abbruchkriterium verwendest (a²-b²) gibt es keinen fixen Grenzwert für die Distanz |a-b|.

    Jetzt sollte aber noch der Begriff "Zyclus" vs. Iteration geklärt werden, wie mir auffällt.

    Sorry, ich meinte damit Iterationen.

    aber es ist sicher, dass in Vers.1 viel weniger Codezeilen pro Iteration ausgeführt werden.

    Naja, wie viele Codezeilen es sind ist nicht unbedingt wichtig, weil nicht jede Codezeile gleich lange dauert. Eine Addition von zwei 360 Bit Zahlen ist viel schneller als eine Multiplikation von zwei solchen Zahlen und diese ist wiederrum viel schneller als eine Division usw.

    Ist dein Code Open-Source? Falls ja könnte ich mir den ja mal ansehen und selbst ein wenig damit rumspielen.



  • @hustbaer Hätte ich nichts dagegen. Der Code ist bisher privat und unveröffendlicht. Was interessiert Dich? Der ganze Explorer, oder nur Fixpoint (Ist nur für diese Anwendung gemacht (geeignet?)). Ist halt alles mit c++Builder 2009 gemacht und nicht unbedingt State of the Art.

    |a-b| wäre natürlich ideal. Aber 1. will nicht Rechnzeit mit sqrt() verschwenden, und 2. a²-b² funktioniert annähernd genausgut.



  • OK. Ich hab meine aktuelle Programmversion auf https://github.com/RudiMBM/DeepChaos bereitgestellt. Da ist das, was hier besprochen wurde, schon drin.
    Ich wünsch einen schönen Osterspaß.



  • Danke. Und sorry für die späte Antwort. Ich werde es mir mal ansehen, schauen ob ich das mit Visual Studio zum Laufen bekommen.

    ps: Achje, nein, wenn dann hätte mich der Source interessiert. Um verschiedene Dinge auszuprobieren.



  • @hustbaer Ich hab gezögert, ich glaub nicht, dass es mit was anderem als Borlandc++2009 compilierbar ist. Ich hab den Fehler begangen LMD-Tools einzubinden. Nach nem Absturz 2012 hatte immense Probleme das zu rekonstruieren. Ich kann zum anschauen schon Source reinstellen. Compilieren aber habe ich wenig Hoffnung. Und welche Funktionen interessieren Dich? Könnte sein, dass diese über einige Classen verteilt sind. Ein gewöhliches MBM-Programm, wie es hundertfach auf Github gibt, ist meines nicht. Und wenn Du an der Source rumschrauben willst, wirst Du dich erst mal ne längere Weile einfuchsen müssen. Liegt nicht an Dir, ich habs kompliziert gemacht. Ich das Projekt seit 8 Jahren nicht angefasst, jetzt in Quaratäne war mir langweilig und ich habs wieder ausgegraben. Ich musste selber wieder reinkommen.
    Hast Du die exe wenigstens mal ausprobiert?



  • Hallo, ich habe nun auch Sourcecode nach github kopiert. Ich bin gespannt, was Ihr damit macht. Ich hoffe, Ihr teilt mir das mit.



  • Ah, ja, ich hatte die Hoffnung gehabt dass man das mit mittlerem Aufwand mit nem anderen Compiler zum Laufen bekommen könnte. Dann wäre es einfach gewesen da ein paar Änderungen zu machen und zu schauen was die bringen. Aber sieht so aus als wäre das ziemlich unmöglich 🙂

    Macht nix. Trotzdem danke für's Hochladen!



  • Es klingt so, als hättest Du eine Idee. Falls Du sie mir mitteilen willst, kann ich sie ja einbauen und guggen was passiert. Wenn nicht, wäre es schade, es hat bisher Spass gemacht.



  • Nicht viel mehr als was ich bisher schon geschrieben habe. Ich würde z.B. mal beide Abbruchskriterien gleichzeitig laufen lassen und schauen ob das was bringt. Bzw. es würde mich auch interessieren wieso mein Verfahren langsamer ist als deins -- ich vermute immer noch dass es einfach später (nach mehr Iterationen) abbricht. Denn wie ich schon geschrieben habe: eine Addition/Subtraktion ist viel billiger als eine Multiplikation, speziell bei so grossen Zahlen.

    Bzw. ich fände es auch interessant einfach ein paar Dinge mitzufählen. z.B. wie oft wurde Abgebrochen und nach der wie vielten Iteration. Und bei meiner Variante dann auch noch: war der Punkt unmittelbar vor dem Abbruch weiter als z.B. 2 Epsilon entfernt oder nicht? Dann wüsste man wie viele Ausgangswerte zu einem einzigen Wert konvergieren und wie viele in einem stabilen Zyklus enden.

    Ebenso fände ich interessant eine andere Abstandsmetrik zu verwenden. Ja, dazu muss man ein klein wenig mehr rechnen, aber dafür kann man auch früher abbrechen. Weil die Fläche von a²-b² halt (u.U. deutlich) grösser ist als |a-b|.


Anmelden zum Antworten