Entwickler-Ecke

Algorithmen, Optimierung und Assembler - For-Schleife zwingt rechner in die Knie


MJDarknet - So 11.01.09 16:32
Titel: For-Schleife zwingt rechner in die Knie
Hallo,

Ich möchte/muss für ein Fachreferat ein Programm schreiben um das Empirische Gesetz der großen Zahlen darzustellen.
Um die Absoluten Häufigkeiten der einzelnen Elementarereignisse zu ermitteln benutze ich ein Integerarray dessen Größe der Anzahl der Elementarereignisse entspricht. Jeder index repräsentiert so eines der Ereignisse des Experiments und ein Zufallsgenerator bestimmt den Index, dessen Wert sich dann um den Wert eins erhöht. Daraus werden dann die relativen Häufigkeiten der einzelnen Elementarereignisse berechnet.

Das ermitteln der Absoluten Häufigkeiten läuft in einer For-Schleife, in der Anzahl der Wiederhohlungen die vorher festgelegt wurden.
Das dauert, wenn ich das Experiment 1Mrd. mal durchführen lasse c.a. 30 Sek. (Was nach meinen Recherchen bei dieser Größenordnung in Ordnung zu sein scheint.)
Nun wollte ich aber einen "Bitte Warten..." Dialog in der Zeit der Durchführung einblenden, der den Fortschritt des Experiments anhand einer ProgressBar darstellt.
Das hat auch so weit funktioniert. Der Wert der Progressbar wird in der Schleife der Absoluten Häufigkeiten mit berechnet. Allerdings verzögert sich der Ablauf des Programms wesentlich, wenn ich in die Schleife eine zusätzliche Anweisung schreibe. Bei 100Mio. Wiederhohlungen dauert es ungefähr 4 mal so lange das Experiment durchzuführen als bei 1Mrd. mal mit nur einer Anweisung in der Schleife. Bei 1Mrd. Wiederhohlungen stürtz das Programm anscheinend sogar ab. Jedenfalls ist er nach 10 Min. noch immer nicht fertig.
Kann eine zusätzliche Anweisung so eine Verzögerung auslösen oder mache ich was falsch?

Ich poste mal den Code der verursachenden Funktion.


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
//Ermittelt die Absolute Häufigkeit
        private void GetAbsProb(int iElEvAmount, int iRepeat) //Anzahl Elementarereignisse, Anzahl Wiederhohlungen
        {
            Random rnd = new Random();
            int[] iAbsProb = new int[iElEvAmount];

            for (int i = 0; i < iRepeat; i++)
            {
                iAbsProb[rnd.Next(iElEvAmount)]++;
                pbExp.Value++;
            }

            FillTable(iRepeat, iElEvAmount, iAbsProb, GetRelProb(iElEvAmount, iAbsProb));
        }


Hat jemand eine Lösung für mich? Das würde mich sehr freuen... Ist zwar nicht essentiell für das Programm, sieht aber schöner aus wenn ich das hinbekommen würde.


platzwart - So 11.01.09 16:43

das anzeigen schluckt immer unmengen an zeit. versuche, die anzahl der anzeigenaktualisierungen zu verringern (z.b. nur bei jedem millionsten durchlauf einmal aktualisieren).


MJDarknet - So 11.01.09 17:05

user profile iconplatzwart hat folgendes geschrieben Zum zitierten Posting springen:
das anzeigen schluckt immer unmengen an zeit. versuche, die anzahl der anzeigenaktualisierungen zu verringern (z.b. nur bei jedem millionsten durchlauf einmal aktualisieren).


Ah, vielen Dank. Ja das hat funktioniert. Hätte nicht gedacht das es so viel ausmacht. Alle 500 mal reicht aus, jetzt ist er genauso schnell wie mit nur einer Anweisung und braucht für 1 Mrd. durchläufe 30 Sek. :D


JüTho - So 11.01.09 17:34

Hallo und noch :welcome:

Noch ein zusätzlicher Hinweis (das geht aus dem Code-Auszug nicht hervor): Random sollte nur einmal pro Formular (oder pro Applikation) erzeugt werden und nicht bei jedem neuen Aufruf derselben Methode. Wenn diese "zu schnell hintereinander" aufgerufen wird, ähneln sich die Zufallszahlen zu sehr.

Zum Hauptproblem: Die Anzeige führt in vielen ähnlichen Situationen zu unerwarteten Problemen. Dann ist meistens ein separater Thread oder BackgroundWorker sinnvoll. (Das hilft Dir wenig, weil Du sowieso auf das Ergebnis warten wolltest; aber es würde das "Einfrieren" der GUI verhindern.)

Gruß Jürgen