Heap Space erhöhen (64bit)

Greeco-K

Mitglied
Hallo zusammen!

Ich brauche mehr speicher da ich den Fehler bekomme, dass nicht genügend Heap Space zur Verfügung steht. Jetzt kenne ich bereits die Möglichkeit beim Aufruf mit "Xmx" und "Xms" den Speicher hoch zu setzen. Ich benötige aber mehr als mit der 32bit Version möglich sind. Jetzt habe ich auch schon von dem "d64" argument gelesen und das die Umgebungsvariable (Windows) auf den Pfad der 64bit Version umgesetzt werden muss. Leider funktioniert der folgende batch Aufruf nicht:

set JAVA_HOME=C:/Program Files/Java/jdk1.6.0_27;%JAVA_HOME%
set PATH=C:/Program Files/Java/jdk1.6.0_27/bin;%PATH%

java -d64 -Xms512m -Xmx4096m MeinJavaProgramm
pause
exit

Ich bekomme den Fehler "Unrecognized option: -d64"
Was mache ich denn hier falsch?!
Bin für jede Hilfe Dank!

Liebe Grüße
 
Wie sieht denn genau deine Konfiguration aus ? Du hast ein 64-Bit Windows und ein 64-Bit Java da drauf ?
Vielleicht ist jdk 1.6 ein bisschen alt? Kannst du nicht mal ein aktuelles aufspielen ? 1.8.xxx
 
Ach! Ich kann meine Frage selbst beantworten! =D

d64 ist nur für Linux und Mac. Für Windows einfach den Path umsetzen wie es oben steht und dann ohne d64 einfach aufrufen. Dann gehts!
 
Bei 32 Bit ist nicht mehr als 1600-1700MB Heapspace drin. Ich habe sehr große 2 dimensionale Arrays. Die erste Dimension ist teilweise über 1.000.000 Einträge lang. Wenn dann in jeder "Zeile" 10 Double Werte stehen sprängt man das anscheinend.

Ich bin aber durchaus an effizienter und vor allem schneller Ansätzen interessiert. Aber irgendwohin muss ich ja meine Daten speichern.... ?!
 
Stimmt schon... 8 byte (pro double) x 1.000.000 x 10 = 80 Million byte bzw 80 Megabyte

Ich habe aber auch ähnlich lange Listen, weiß nicht ob die Speicherintensiver sind. Weiß aber auch nicht was Java dann intern noch macht wenn die verglichen und durchsucht werden müssen usw.

Bin kein Programmierer... Es gibt sicher effizientere Möglichkeiten das umzusetzen. Versuche eben nur den Fehler dem ich mit meinem Code begegne zu lösen. :/
 
Wenn möglich sollte man bei 2D Arrays die erste Dimension möglichst klein halten.
Da Java keine echten 2D Arrays hat, machst du im Grunde nur ein Array aus Arrays. Und da ist es eben um Welten besser wenn du ein [10][1.000.000] Array hast anstatt ein [1.000.000][10] Array.
Im ersten Fall sind es eben nur 10 Arrays von denen jedes 1.000.000 lang ist. Im letzteren Fall hat man eben 1.000.000 Arrays von denen jedes 10 lang ist. Das macht schon Performance technisch extrem viel aus.

Aber Grundsätzlich wirst du irgendwas anderes falsch machen, denn selbst mit [1.000.000][10] kommt man nicht annähernd auf so einen hohen RAM Verbrauch
 
Zuletzt bearbeitet:
Wann brauchst du denn soviel Platz ? Von Anfang an oder kam der ganz oben erwähnte Fehler nach einer gewissen (Lauf-)Zeit ? Vielleicht hast du ja irgendwo Speicherlecks und die GC kann nicht aufräumen ?
 
Bleibt immer wieder die Frage wozu braucht man über 1Mio Objekte, egal welcher Art, im Heap. In einer Datenbank macht das ja noch Sinn aber im Heap braucht das kein Mensch.
 
Bleibt immer wieder die Frage wozu braucht man über 1Mio Objekte
Wir kennen ja seine Anwendung nicht. Es handelt sich offenbar um Millionen von Zahlen mit denen offensichtlich auch gerechnet wird. Und ich könnte mir vorstellen dass man die im Speicher halten muss um schnell genug zu sein. Aber trotzdem wären das ja 200 Mio. doubles die er in den 1,6 GB unterbringen kann bei denen er einen Fehler kriegt. Deshalb vermute ich da auch noch irgendwo ein Speicherleck.
 
Hallo nochmal!
Vielen Dank für die rege Beteiligung! Ich habe nochmal geschaut, wann der Fehler genau geworfen wird. Er entsteht beim einlesen meiner Daten. Alle Zahlen stehen ersteinmal in einer Textdatei. Die ist mitunter rießig (3.771.037 KB in meinem großen Beispielfall). Ich lese die Datei ersteinmal ein und extrahiere dann die Zahlen und schreibe sie in verschiedene Arrays mit denen ich anschließend weiterarbeite.

Die Methode zum einlesen sieht folgendermaßen aus:

Java:
//****************************************************
// Reads in a file and return it as a String List
//****************************************************
public List<String> List(String FileName) throws IOException {
  String line;
  List<String> List = new ArrayList<String>();

  BufferedReader reader = new BufferedReader(new FileReader(FileName));
  while((line = reader.readLine()) != null) {
    List.add(line);
  }
  reader.close();
  return List;
}
Gibt es Ideen?
Vielen Dank nochmal!
 
Zuletzt bearbeitet von einem Moderator:
Wenn du eine Datei von 3 GByte einliest ist klar dass du ein bisschen Platz dafür brauchst. Aber interessiert denn der ganze Inhalt der Datei ? Oder stehen da jeweils in den Zeilen versteckt ein paar Zahlen ? Du könntest dann die Datei zeilenweise einlesen und jede Zeile parsen und die Info rausholen die dich interessiert.

Edit: so wie du es vermutlich ja jetzt mit deiner String-List machst.
 
Zuletzt bearbeitet:
Ich habe einen Fehler gemacht. Die Datei die eingelesen wird ist nur 250MB groß. Da brauche ich auch die ganze Datei. Die super große mit 3GB gehe ich Zeile für Zeile durch und prüfe ob in der Zeile Daten stehen die mich interessieren.

Heapspace Exception kommt also schon bei einer 250MB Datei...
 
Wenn du wirklich(!) alle Daten brauchst, gibt es nur zwei Möglichkeiten:
1. Heapspace vergrößern und alles Laden
2. Heapspace belassen und Daten on demand nachladen

Wenn das jetzt nicht zielführend ist, dann solltest du dir Überlegen, welche Daten du wirklich brauchst und deinen Algorithmus ändern.
 
Na dann zeige ich mal den ganzen Code bis zu der Stelle an der der Fehler kommt:

Zuerst wird in der main eine Methode aufgerufen die eine Config Datei einließt und einige Parameter setzt die anschließend an die Methode RunPostProcessing übergeben werden

Java:
private static void RunPostProcessing (StringBuilder DatFileName, StringBuilder DiagFileName, StringBuilder PCHFileName, StringBuilder NodeFaceFileName, StringBuilder DatFilePrepLogName, StringBuilder MeshType, StringBuilder Function, List<Integer> NodeIDs, double [][] position, List<String> faces, boolean[] data_ordered) throws IOException {

Routines routine = new Routines ();
Read read = new Read();

//###### PARAMETERS ######
// General Parameters to read in FE Files (.pch, .dat, 'node_face_relations.text')

int GridNumber = routine.GetGridNumber(DiagFileName.toString());
int DisplacementNumber = routine.GetDisplacementNumber(DatFilePrepLogName.toString());
int ElementStressNumber = routine.GetStressNumber(DatFilePrepLogName.toString());
int SPCForceNumber = routine.GetSPCForceNumber(DatFilePrepLogName.toString());

List<Integer> SPCNodeIDs = routine.GetSPCNodeIDs(DatFilePrepLogName.toString());

//Arrays to save FE Data into
double [][] GridData = new double[GridNumber][4];
double [][] DisplacementData = new double[DisplacementNumber][7];
double [][] ElementStressData = new double [ElementStressNumber][11];
//double [][] NodeStressData = new double [4*ElementStressNumber][11];
double [][] SPCForceData = new double [SPCForceNumber][7];
List<String> NodeFaceData = new ArrayList<String>();
List<String> NodeElementRelationStrings = new ArrayList<String>();
List<String> DatFile = new ArrayList<String>();

// ############ Reading in the FE Data #############
DatFile = read.List(DatFileName.toString());

// Hier wird dann der Fehler geworfen! Die Methode "List" steht im Beitrag oben"
 
Mal schrittweise dahin debuggen und im guten alten Taskmanager (falls du sonst keine Tools hast) den Speicherbedarf des Prozesses beobachten. (wie gross sind denn die ganzen Konstanten bei den double-Arrays ?)
 
Hier die Größe der Konstanten:

GridNumber = 1309898
DisplacementNumber = 1309898
ElementStressNumber = 851119
SPCForceNumber = 1

Wenn ich vor der Stelle wo der Heapspace Fehler kommt pausiere und in den Taskmanager schauer steht hinter "java.exe" Memory 632.592K. Danach folgt die Methode von oben und es kommt natürlich auch in Eclipse der Heapspace Meldung.
 
Mit den ganzen double[][] Arrays allokierst du schon vorher Speicherplatz! Wenn du dann auch noch die Datei einlest, dann läuft der Speicher über. Also nach und nach die Arrays allokieren und die Datei parsen, wäre so mein Tipp.
 
Das wird vermutlich nicht gehen weil er die Arrays beim parsen braucht. Und ob das Programm nnun beim Einlesen der Datei abstürzt oder nach dem Einlesen beim parsen ist egal. Und er braucht ja die Datei im Speicher, sagt er.
Ich hab die Lösung schon gepostet: #19
Oder man parsed die Daten eben gleich in die Arrays Zeile für Zeile, dann hat man auch keine Probleme. Wenn man überhaupt alle Arrays dafür erstellen kann.
 
Da brauche ich auch die ganze Datei.
Wenn diese Aussage so steht dann hilft nur mehr Speicher. Wobei mir aber die Aussage dass sein Programm schon 600MB verbraucht bevor er an die Stelle kommt wo er die Datei einliest schon komisch vorkommt wo er doch vorher nur eine config-Datei einliest und ein paar Konstanten speichert. Und warum verbrät er in der List-Methode noch mal fast ein GByte um eine Datei von 250 MByte einzulesen ?
 
Danke nochmal für die rege Beteiligung hier!

Ich habe nochmal etwas nachgedacht und bin zu der Erkenntnis gekommen, dass ich wahrscheinlich auch die 250MB Datei Zeile für Zeile einlesen könnte. Würde sehr wahrscheinlich auch gehen.

Prinzipiell würde mich aber interessieren ob eine effiziente Speichernutzung mein Script auch schneller durchlaufen lassen würde? Mein Rechner hat 100GB Arbeitsspeicher, ob da jetzt 1GB, 4GB oder 20GB benötigt werden interessiert mich eigentlich wenig. Geschwindigkeit wäre allerdings schon interessant.

Liebe Grüße
 
Bitte Klär mich doch mal einer auf was du mit mehreren hundert Millionen Doubles machst. Ich programmiere jetzt seit über 30 Jahren aber habe das noch nie benötigt und das obwohl ich davon zwanzig Jahre Software für digitalen Videoschnitt geschrieben habe...
 
Mein Rechner hat 100GB Arbeitsspeicher, ob da jetzt 1GB, 4GB oder 20GB benötigt werden interessiert mich eigentlich wenig.
100GB RAM? Kann ich mir kaum vorstellen, sofern du nicht zufällig ein HPC System nutzt...wobei dann natürlich die Frage ist warum man Java benutzt^^

Geschwindigkeit wäre allerdings schon interessant.
Solange wir deinen Code und den Aufbau der Dateien nicht kennen, können wir dir da nicht viel zu sagen.
 
Nein der Rechner steht unter meinem Schreibtisch. Ich arbeite aber daran das ganze auch mal auf einen Cluster zu kriegen, ist aber ein anderes Thema. Die Auswertung der Ergebnisse ist ja nur ein Schritt. Aber ich werde eher mehrere Rechnungen parallel laufen lassen als zu versuchen eine einzelne Rechnung durch mehr Rechenleistung schneller zu bewerkstelligen. Für meine Anwendung ist es besser z.B. 8 gleichzeitig laufen zu lassen.

Ich nutze eben Java, weil ich Java kann. Sofern man bei meinen Kenntnissen von "Können" sprechen möchte...
 
Ich habe die Stelle gerade umgeschrieben und lese jetzt auch die 250MB Datei Zeile für Zeile ein. Rechenzeit ist die gleiche, Heapspace reicht dann aber aus und im Taskmanager stehen ca. 650MB Memory.

Werde für alle Fälle aber trotzdem weiterhin die 64bit Version verwenden und den Xmx Wert hochschrauben. Dürfte keine Nachteile haben oder?

@Dunkel:
Kannst du das kurz beschreiben?
 
Wieso willst du das mit Java machen? Dass du Java kannst, ist da kein ausreichender Grund. Java ist zum Rechnen einfach ungeeignet. Das lesen von benötigten Daten aus dem RAM wird furchtbar langsam werden, wenn du keine Kontrolle darüber hast, welche Daten gerade wo herumgeistern. Es macht einen significaten Unterschied, wenn du mehr Kontrolle darüber hast, welche Daten gerade in den einzelnen Cache-Level der CPU liegen.

Wieso willst du das überhaupt selbst machen? Solver für LGS gibt es ja nun wirklich zu Hauf. Du solltest dir natürlich nur einen passenden suchen, der deine Bandstruktur beibehält und dein LGS dann auch in linearer Zeit löst, sonst wartest du ja Jahrzehnte auf das Ergebnis 🙂 Wenn du dich mit FEM beschäftigst, dann wirst du das aber sicher alles wissen.
 
Dukel hat damit sicher Apache Spark oder den Vorgänger Apache Hadoop gemeint. Das sind - wie ich auch bereits erwähnt hatte - Big Data Computation Libraries, die im Cluster arbeiten.

Zu deinen Fragen: 64 Bit Version kannst du ruhig verwenden und den Heapspace raufschrauben, denn du weißt, dass du große Datenmengen verarbeitest und die im Hauptspeicher halten musst.

Ich hätte da noch eine andere Lösungsidee: Es gibt genügend FEM-Frameworks die dir das schon rechnen können, vielleicht schaust du dir ein solches für Java an.
 
Und du solltest versuchen deine Rechnungen soweit es geht parallel durchzuführen das bringt meiner Meinung nach am meisten.

Worauf beruht diese Meinung? Das lässt sich leicht sagen, aber das effiziente Lösen solcher Gleichungssystem ist nun doch ein sehr komplexes Thema, zumal man sie ohnehin (fast) immer nur näherungsweise lösen kann. Für solche Band-Matrizen sind meist Iterative Verfahren die bessere Wahl, bei denen man die Struktur der Matrix ausnutzt. Viel parallelisieren lässt sich da nicht bei den Algorithmen, die eben diese Struktur beibehalten. (Ich mag mich hier auch irren, meine mich aber schwammig an Studieninhalte von damals zu erinnern...) Einzelne Matrix-Vektor Produkte könnte man parallel berechnen, aber der Nutzen fällt da eigentlich nicht sonderlich ins Gewicht. Ich könne mir sogar vorstellen, dass in Java der nötige Overhead das Verfahren dadurch eher ausbremst. Wo wir aber wieder beim anderen Thema wären: Sowas sollte man gar nicht erst mit Java machen.
 
Worauf beruht diese Meinung?
Ich meinte ja auch nicht dass er ein LGS parallel lösen soll. Aber vielleicht ist seine Anwendung ja so strukturiert dass er mehrere solcher Gleichungssystem zu lösen hat. Deshalb meine Einschränkung "so weit es möglich ist parallel". Und wie @Flown schon sagte: ein Framework suchen das das schon optimal macht. Warum soll das dann nicht in Java gehen. Er wird ja keine Realtime-Anforderungen haben.
 
Ach, LGSs parallel zu lösen macht schon Sinn ... nur bei solchen eben nicht sonderlich.
Dass mehrere dieser Gleichungssystem gleichzeitig zu lösen sind, davon gehe ich aufgrund der Problemdomäne einfach mal nicht aus. Die zugrunde liegenden Diskretisierungen fallen ja auch nicht einfach vom Himmel.
Klar kann man das auch in Java berechnen, aber das ist ungefähr so, als würde ich mit nem BobbyCar Formel1 fahren wollen.
Vielleicht sieht man das aber selbst erst ein, wenn an wirklich mal mit solchen LGS gearbeitet hat.
 
Sollte er damit wirklich meinen, dass er 8 solcher LGS gleichzeitig lösen will, dann kann man das natürlich leicht parallel durchführen. Das hab ich auch tatsächlich überlesen 😳
 
Habe hier kurz nicht reingeschaut und die Diskussion ist ja fleißig weiter gegangen.

Dennoch vielleicht ein paar klärende Sätze zum Abschluss.
Es geht darum mithilfe von einem Skript die Ergebnisse einer FEM Berechnung automatisiert auszuwerten.

Zum Lösen des FE Problems nutze ich "natürlich" eine kommerzielle Software. Es geht nur um die automatisierte Auswertung der Ergebnisse! Es geht dann beispielsweise darum, automatisiert die höchste oder die mittlere Spannung auf einer Fläche auszuwerten.

Sollte er damit wirklich meinen, dass er 8 solcher LGS gleichzeitig lösen will, dann kann man das natürlich leicht parallel durchführen.

So ist es. Sind aber nicht nur 8 sondern eher 50 und manchmal auch 500.

Die zugrunde liegenden Diskretisierungen fallen ja auch nicht einfach vom Himmel.

Stimmt! =D
Aber ich weiß schon warum ich die alle rechnen möchte! 😉
 

Zurück
Oben