ubuntuusers.de

Lange dauerndes Java Programm

Status: Ungelöst | Ubuntu-Version: Server 22.04 (Jammy Jellyfish)
Antworten |

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17604

Wohnort: Berlin

homer65 schrieb:

Hallo Zusammen, habe mit VisualVM das Profiling gemacht. Leider weiss ich wirklich nicht was zu verbessern ist. Es ist der folgende Konstruktor der als Hauptlast Verursacher ausgemacht wird.

1
2
3
4
5
6
7
8
public Pauli(int n)
	{
		paulikette = new int[n];
		for (int i=0;i<n;i++)
		{
			paulikette[i] = 0;
		}
	}

Hierbei ist n immer 50. Die Matrizen haben die Dimension 2 hoch 50. Aufgrund ihrer speziellen Form lassen sie sich aber mit O(n) Schritten multiplizieren und auch die Spur ist O(n). Also noch nicht so dramatisch. Nur die Anzahl der Multiplikation ist gigantisch. Und für jede Multiplikation wird eine neue Matrix (Pauli) erzeugt. Hmh vielleicht kann ich das ständige Neuinitialisieren vermeiden. Mal nachdenken.

Ja, ein int-Array wird von Java automatisch mit Nullen initialisiert und das ist auch garantiert, kein Grund da nochmal drüberzugehen.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17604

Wohnort: Berlin

verdooft schrieb:

Ich hab mal was mit Zufallszahlen und Summen gemacht, da war C(++) super flott. Es spricht ja auch nichts dagegen, das einfach mal in verschiedenen Sprachen umzusetzen und dann die schnellste Variante zu verwenden?

Wenn man schon nicht für die erste Sprache der Wahl weiß, dass int-Arrays garantiert mit 0en initialisiert werden, dann wird Herumexperimentieren mit anderen Sprachen wahrscheinlich nur zu Zufallsbefunden führen.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13175

homer65 schrieb:

1
2
3
4
5
6
7
8
public Pauli(int n)
	{
		paulikette = new int[n];
		for (int i=0;i<n;i++)
		{
			paulikette[i] = 0;
		}
	}

Die Initialisierung ist vielleicht sogar überflüssig. Schau mal in die Language Spec. Falls nicht, gibt es da viel eleganter eine Methode in Klasse Array.

homer65

(Themenstarter)
Avatar von homer65

Anmeldungsdatum:
8. November 2005

Beiträge: 574

Wohnort: bochum, germany

Ja die Initialisierung war überflüssig. Asche auf mein Haupt. Hat aber leider nichts für die Performance gebracht. Habe noch eine Weile mit dem Profiler geguckt. Die Anwendung ist jetzt um den Faktor drei schneller. Derzeitiger Stand: Er hängt im folgendem Code am längsten fest

1
2
3
		vorfaktor.setRe(p.getVorFaktor().getRe()); 
		vorfaktor.setIm(p.getVorFaktor().getIm());
		paulikette = p.paulikette.clone();

: Ich nehme an die Zeile

1
		paulikette = p.paulikette.clone();

dauert so lange. Da wird ein Array der Länge 50 vom Typ short kopiert. Für mich war es das jetzt erstmal mit Java. Werde nun ersuchen das Ganze mal in C++ zu coden. Mal schaun was dabei rauskommt. Danke an alle für Ihre Ideen. ☺

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17604

Wohnort: Berlin

homer65 schrieb:

Ja die Initialisierung war überflüssig. Asche auf mein Haupt. Hat aber leider nichts für die Performance gebracht. Habe noch eine Weile mit dem Profiler geguckt. Die Anwendung ist jetzt um den Faktor drei schneller. Derzeitiger Stand: Er hängt im folgendem Code am längsten fest

1
2
3
		vorfaktor.setRe(p.getVorFaktor().getRe()); 
		vorfaktor.setIm(p.getVorFaktor().getIm());
		paulikette = p.paulikette.clone();

:

Wenn es nicht das .clone() ist, und Re und Im sind Attribute, und die sind nur deshalb private und werden über {set,get}{Re,Im} angesprochen (analog getVorFaktor), weil es in allen Büchern so vorgeturnt wird, dann könntest Du die Attribute auch public machen und mit

1
2
		vorfaktor.re = (p.getVorFaktor().re); 
		vorfaktor.im = (p.getVorFaktor().im);

bzw.

1
2
		vorfaktor.re = p.vorFaktor.re); 
		vorfaktor.im = p.vorFaktor.im);

direkt zugreifen, ohne Funktion, was einen Deut schneller ist, und messbare Auswirkungen vielleicht zeigt, aber ob spürbare - wohl nur, bei Millionen und Abermillionen Aufrufen.

Es verletzt das Kapselungs- und Geheimnisprinzip der OOP, aber diese sollen ja beim Programmieren unterstützen, nicht im Wege stehen. Die Frage ist dann, ob die Klassen noch in anderen Programmen verwendet werden, ob es andere Verwender gibt, die von der Änderung betroffen wären usw.

Ich nehme an die Zeile

1
		paulikette = p.paulikette.clone();

dauert so lange. Da wird ein Array der Länge 50 vom Typ short kopiert.

Dafür könnte die Hilfsmethode Arrays.copyOf (short[] array, int len); schneller sein - müsstest Du ausprobieren.

Klasse: java.util.Arrays.

1
paulikette = Arrays.copyOf (p.paulikette, 50);

Müsstest Du eben ausprobieren.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13175

homer65 schrieb:

Ich nehme an die Zeile

1
		paulikette = p.paulikette.clone();

dauert so lange.

Was heißt "Du nimmst an"? Wenn Du gleich das ganze Programm in C++ neu schreiben willst, dann würde ich da schon etwas mehr harte Fakten erwarten. Zumal Du bei C++ dann wieder von vorne mit Deinen Optimierungen anfängst.

Da wird ein Array der Länge 50 vom Typ short kopiert. Für mich war es das jetzt erstmal mit Java. Werde nun ersuchen das Ganze mal in C++ zu coden.

Das halt ich für voreilig. Wenn Du copy on write benutzt, dann kannst Du ggf. das Array auch einfach referenzieren. Siehe auch die Anmerkungen von user_unknown. Mit dem, was wir bisher gesehen haben, können wir da aber nicht konkreter helfen.

homer65

(Themenstarter)
Avatar von homer65

Anmeldungsdatum:
8. November 2005

Beiträge: 574

Wohnort: bochum, germany

Danke nochmals für die andauernde Mühen. Das Array muss leider kopiert werden. Ein referenzieren geht nicht. Da der Ausgangsstand mehrfach unverändert benutzt wird und das kopierte Array wird direkt verändert. Auch die andere vorgeschlagene Copy Methode habe ich ausprobiert. Keine Verbesserung in der Performance. Soweit so schlecht. ☹

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11249

Wohnort: München

Wenn du den Array für die Arbeitsdaten einmalig initialisierst und dann lediglich in jedem weiteren Durchlauf komplett überschreibst (so dass kein Müll zurückbleibt), würde ich mal System.arrayCopy probieren - damit spart man sich gegenüber den anderen Methoden zumindest das Initialisieren eines neuen Arrays: https://www.geeksforgeeks.org/system-arraycopy-in-java/

homer65

(Themenstarter)
Avatar von homer65

Anmeldungsdatum:
8. November 2005

Beiträge: 574

Wohnort: bochum, germany

Danke seahawk1986, aber leider bringt auch das keine Verbesserung. ☹

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13175

homer65 schrieb:

Das Array muss leider kopiert werden. Ein referenzieren geht nicht. Da der Ausgangsstand mehrfach unverändert benutzt wird und das kopierte Array wird direkt verändert.

Verstehe ich Dich richtig, dass jedes neu angelegte int[] auf jeden Fall verändert wird, so dass sich der Aufwand für die Copy & Write Implementierung nicht lohnt? Aber andererseits sagst Du, dass "der Ausgangsstand mehrfach unverändert benutzt wird". Würde sich da nicht lohnen, für alle diese Fälle dasselbe int[] zu verwenden?

Neral

Anmeldungsdatum:
3. Oktober 2007

Beiträge: 230

@homer65: Wie lang ist denn der Code insgesamt? Vielleicht einfach mal komplett zeigen, dann muss man nicht so im Dunkeln stochern und könnte ggf. konkretere Hinweise geben.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17604

Wohnort: Berlin

seahawk1986 schrieb:

Wenn du den Array für die Arbeitsdaten einmalig initialisierst und dann lediglich in jedem weiteren Durchlauf komplett überschreibst (so dass kein Müll zurückbleibt), würde ich mal System.arrayCopy probieren - damit spart man sich gegenüber den anderen Methoden zumindest das Initialisieren eines neuen Arrays: https://www.geeksforgeeks.org/system-arraycopy-in-java/

Nunja, das Initialisieren des Arrays übernimmt dann System.arrayCopy, sonst bliebe das Array ja uninitialisiert. Arrays.copyOf übernimmt ja auch die Initialisierung.

Und was könnte der Vorteil gegenüber Arrays.copyOf sein, welches eine spezialisierte Methode für int[] und short[] usw. bereithält, während System.arrayCopy mit Object[] arbeitet - das kann kaum schneller sein, aber bitte, probier es aus.

Arrays.copyOf gibt es seit Java 1.6, für System.arrayCopy habe ich keinen Versionsmarker in der Doku gefunden.

homer65

(Themenstarter)
Avatar von homer65

Anmeldungsdatum:
8. November 2005

Beiträge: 574

Wohnort: bochum, germany

Nur falls es noch jemanden interessiert. Habe die Berechnung jetzt auch in Fortran programmiert. In der Laufzeit gibt es praktisch keinen Unterschied. Allerdings fiel mir dabei auf, das ich die Symmetrie des Problems ausnutzen kann. Die Laufzeit geht dadurch um einen Faktor 100 runter. ☺

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13175

homer65 schrieb:

Allerdings fiel mir dabei auf, das ich die Symmetrie des Problems ausnutzen kann. Die Laufzeit geht dadurch um einen Faktor 100 runter. ☺

Cool! Was für ein Erfolg!

Antworten |