Announcement

Collapse
No announcement yet.

Code optimieren

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Code optimieren

    Halli Hallo...

    [wens nich interessiert überspringen]
    Ich weiß nicht ob ich hier in der richtigen Rubrik gelandet bin, aber wird schon irgendwie hinhaun.^^ Im Rahmen meines Studiums sollte ein Fraktalgenerator programmiert werden und zwar in C. Naja das hab ich zwar gemacht, aber da ich die Sprache nich gerade mag (geschmackssache), bin ich umgeschwenkt auf Java, genauergesagt J#. Die schönen Bilder haben mich einfach mitgerissen und ich habe das Programm recht gut ausgebaut. Da das setzen von Pixeln mittels GDI+ ziemlich langsam erfolgt, habe ich mich außerdem noch etwas in DirectX eingearbeitet. Das Zeichnen erfolgt nun darüber...
    [und hier weiterlesen]

    Nun aber zur Frage: Ich überlege schon die ganze Zeit wie ich diesen Code hier optimieren könnte:

    Code:
    for (i = 0; i < konstanten.Xpoints(); i++)
    		{
    			wx = ((double)i) * (konstanten.Xmax() - konstanten.Xmin()) / ((double)konstanten.Xpoints()) + konstanten.Xmin();
    
    			for (j = 0; j < konstanten.Ypoints(); j++)
    			{
    				wy = ((double)j) * (konstanten.Ymin() - konstanten.Ymax()) / ((double)konstanten.Ypoints()) + konstanten.Ymax();
    
    				if (typ)
    				{
    					it = GetItera(wx, wy, vx, vy);
    				}
    				else
    				{
    					it = GetItera(vx, vy, wx, wy);
    				}
    Und zwar ist es so, dass sich der Wert der Variable typ innerhalb der Schleife nicht ändert. D.h. es wird verdammt oft geprüft ob typ true oder false ist, obwohl das Ergebnis längst feststeht.

    Mir ist bewusst dass ich bereits vor der Schleife eine Verzweigung machen könnte. Somit würde die Abfrage nur einmal laufen. Da müsste die Schleife aber 2 mal im Code enthalten sein mit den jeweilig unterschiedlichen Aufrufen von GetItera, was ich ziemlich doof finde.

    Kennt jemand eine Möglichkeit den Code zu optimieren? Oder gibt es irgendwie eine Möglichkeit in der Art:

    Schleife: GetItera()

    mit einer vorherigen Abfrage wird der Inhalt der Prozedur GetItera() geändert.

    Danke schon mal.

  • #2
    Hallo,

    der Vorteil der .NET-Sprachen wie VB, C# oder J# liegt darin, dass deren Kompiler nur Sourcecode-Generatoren sind, die MSIL-Code (Microsoft Intermediate Language) generieren. Somit kann man dort nachsehen, ob der Kompiler bereits eine Optimierung aufgrund des feststehenden typ-Wertes vorgenommen hat. Der IL Disassembler (ILDASM.EXE) ist Bestandteil des .NET Framework SDK.

    Aber auch dann, wenn in MSIL noch keine Optimierung erkennbar ist, kann immer noch der Just-In-Time-Compiler der CLR zur Laufzeit dies nachholen.

    Letzendlich verschafft nur ein Experiment die gesuchte Information:

    1. Ausführungszeit mit der if-Abfrage messen.
    2. Ausführungszeit ohne die if-Abfrage messen.

    Wenn beide Zeiten identisch sind, wurde a) entweder automatisch optimiert oder b) die if-Abfrage fällt nicht ins Gewicht.

    Comment


    • #3
      Habs vorhin mal ausprobiert mittels DateTime... Scheint wirklich nix auszumachen.

      Jetz haben sich aber noch 2 Fragen ergeben und zwar:

      1. Also normalerweise dauert die Fraktalberechnung nich länger als 0,3s. Aber falls ich meinetwegen als Iterationszahl 2000 nehme, dann dauert das knapp 10s, je nach Bereich den ich analysiere. Wenn ich während dieser Zeit ins Form klicke, dann bringt Windows die Nachricht: Anwendung reagiert nicht. Nachdem das Fraktal berechnet wurde is alles wieder iO.

      Wie kann ich das verhindern? Es is ja nich so dass es nich reagiert, es dauert halt nur...

      2. Welche Datentypen in .NET gibt es mit erhöhter Genauigkeit? Ich habe festgestellt, dass double etwas ungenau ist wenn ich weit in das Fraktal reinzoome. Der Datentyp Decimal ist da auch nicht unbedingt besser, weil ich die Operatoren +, -, * usw nicht anwenden kann. (naja ich kann die Funktionen der Klasse Decimal verwenden, is aber nich grade komfortabel)

      Was gibt es da für Möglichkeiten?

      Comment


      • #4
        Probier als Zeitmesser bitte mal Environment.TickCount. DateTime ist zu ungenau.

        Comment


        • #5
          Hallo,

          Wenn ich während dieser Zeit ins Form klicke, dann bringt Windows die Nachricht: Anwendung reagiert nicht.
          auch eine .NET-Anwendung setzt bei einem Fenster auf das Win32-API auf, so dass die Botschaftswarteschlange von Windows über eine Message Loop regelmäßig ausgelesen werden muss. Sobald Windows erkennt, dass ein Thread der Anwendung die abgelegten Botschaften nicht innerhalb eines Zeitfensters abholt, zeigt Windows die Info "Anwendung reagiert nicht" an.

          Wie kann ich das verhindern?
          Die saubere Lösung ist die strikte Trennung zwischen Benutzeroberfläche (primärer Thread der Anwendung) und der Fraktalberechnung, indem die Berechnung in einen separaten Thread ausgelagert wird. Ab .NET 2.0 steht dazu die extrem bequeme BackgroundWorker-Komponente zur Verfügung.

          Alternativ (als Quick&Dirty-Lösung) kann auch innerhalb der Fraktalberechnung regelmäßig die Application-Methode DoEvents aufgerufen werden, um die Botschaftswarteschlange auszulesen.


          P.S: Für Zeitmessungen ist ab dem .NET-Framework die Stopwatch-Klasse am besten geeignet.

          Comment


          • #6
            Hab jetz alle Verbesserungen eingebaut.

            Der Backgroundworker is ne feine Sache. Funktioniert echt supi. (Ich muss mir echt mal irgendn Buch anschaffen, damit ich vll rauskrieg wo solche Dinge stehn)

            Ähm und Stopwatch hab ich jetz genommen anstatt DateTime.
            Das Verwunderliche an der Zeitmessung ist nur, dass ich absolut schwankende Messungen bekomme. (Sowohl mit DateTime als auch mit Stopwatch, Sowohl mit BackgroundWorker als auch ohne)

            z.B. differiert das bei nem Standard JuliaFraktal von 150ms bis 220ms. (Also es wird exakt das Selbe getan bei jeder neuen Berechnung (denk ich zumindest^^)) Schon komisch. Irgendwie is da irgenwas was bremst. An der Genauigkeit der Zeitmesser kanns ja nich liegen, die is ja wesentlich höher.

            Irgendeine Idee? Liegt das irgendwie an der Thread Priorität?
            Zuletzt editiert von Bommel; 13.03.2007, 14:19.

            Comment


            • #7
              Hallo,

              Das Verwunderliche an der Zeitmessung ist nur, dass ich absolut schwankende Messungen bekomme.
              welche Prozess-Anzahl zeigt der Windows Task-Manager an, wenn die Messung ausgeführt wird? Da die Threads aller Prozesse über Zeitschlitze auf dem gleichen Prozessor ausgeführt werden, geht die unterschiedliche Last der anderen Prozesse mit in das eigene Messergebnis ein.

              Comment


              • #8
                Moin^^,

                Auslastung sind so ziemlich immer 100% und Anzahl der Prozesse ist 50 (nicht wundern ist Vista...).

                Also um es nochmal genauer zu spezifizieren:

                Wenn ich das Fraktal erstmalig erzeuge ist die Dauer recht hoch. Wenn ich dann eine Sekunde warte ist sie auch wieder recht hoch und schwankend.

                Wenn ich aber ununterbrochen Fraktale erzeuge dann ist die Zeit recht niedrig und konstant, d.h. schwankt im Bereich einiger Millisekunden.


                [edit]: Ich stelle grad fest, dass die Ausführung fast nochmal um 50% gesteigert wird, wenn man das Ganze nicht mehr im Debugger laufen lässt. Is ja der Hammer. FAST.

                mal n Bild: http://mitglied.lycos.de/affnbobs/Fraktal.jpg
                Zuletzt editiert von Bommel; 15.03.2007, 00:06.

                Comment


                • #9
                  Hallo,

                  ...wenn man das Ganze nicht mehr im Debugger laufen lässt...
                  das ist kein Wunder, denn beim Debuggen müssen die Optimierungen des JIT-Compilers (Inlining etc.) abgeschaltet werden.

                  Wenn ich das Fraktal erstmalig erzeuge ist die Dauer recht hoch. Wenn ich dann eine Sekunde warte ist sie auch wieder recht hoch und schwankend.
                  Die Frage, zu welchem Zeitpunkt der Garbage Collector die "Leichen" (d.h. die nicht mehr benötigten Objektinstanzen) abräumt, hängt von mehreren Faktoren ab. Wenn der Rechner mit mehreren Kernen ausgestattet ist, kann man zum Test im Eigenschaftsdialog der .NET Framework 2.0 Konfiguration den Garbabe Collector vom Hintergrundmodus auf den Vordergrundmodus schalten. Ergibt sich dann ein anderes Bild?

                  Comment


                  • #10
                    Hab leider nur nen Single Core... Und ich bin zu doof diese Config zu finden.

                    MfG

                    Comment


                    • #11
                      Hallo,

                      die angehängte Grafik zeigt, wie die .NET Framework-Konfiguration aufgerufen wird. Der Eigenschaftsdialog wird dort im Zweig Console Root | .NET Framework 2.0 Configuration | My Computer über das Monitorsymbol aufgerufen.
                      Attached Files

                      Comment


                      • #12
                        Oh man hab rausgefunden an was es liegt:

                        Power Schema: Ausbalanciert..... Der taktet bei Bedarf hoch und das dauert etwas. Wenn ich konstant auf max Mhz laufen hab, dann is die Zeit auch nahezu konstant.

                        Gut, hätten wir das.^^

                        ps: genau in der Computerverwaltung hab ich vergessen zu schaun.^^


                        [edit]: kennt jemand Fraktalgeneratoren die die Zeit anzeigen die sie zur Berechnung benötigt haben? Ich hab da bis jetz nur einen gefunden: ChaosPro, und der is bei weitem langsamer als mein eigens Geschriebener.
                        Zuletzt editiert von Bommel; 18.03.2007, 01:05.

                        Comment

                        Working...
                        X