Seite 1 von 1

Ram läuft über -> wie kriege ich ihn wieder frei?

Verfasst: Freitag 20. Juni 2008, 11:08
von acidk
Hi!

In meinem Programm berechne ich die Distanz von Punkten zueinander und mache hieraus eine Liste von Listen. Das ganze nicht nur für ein Objekt sondern für an die 100.

Das Programm funktioniert und hängt sich nicht auf - aber während des Schleifens läuft zunächst der Ram über - danach geht die Swap Partition in die Knie.

Wenn ich nach jeder Iteration sleep() aufrufe, geht zwar die CPU Leistung runter, der Ram bleibt aber voll.

Gibt es eine Möglichkeit den Ram gezielt zu leeren?
Ich habe keine Ahnung , warum er überläuft, denn die in den entprechenden Funktionen initialisierte Listen (sollten) immer wieder überschrieben werden.

Besten Dank!

Verfasst: Freitag 20. Juni 2008, 11:15
von Leonidas
Vielleicht ist ja der Artikel Hunting Python Memory Leaks was für dich?

Verfasst: Freitag 20. Juni 2008, 12:11
von OldBoy
Ohne Code können wir gut rumrätseln :-/

Verfasst: Freitag 20. Juni 2008, 12:24
von CM
Oder magst Du vielleicht das relevante Snippet zeigen?

edit: Sorry, das Posting von OldBoy wurde mir erst mal nicht angezeigt ...

Verfasst: Freitag 20. Juni 2008, 12:41
von acidk
Das Programm ist ziemlich lang (mittlerweile fast 1000 Zeilen). Ich vermute, dass es an der Distanzberechnung liegt :roll: (ab Zeile 112)

Ich will hier aber auch keinem zumuten meinen Code aufzudröseln -
(und eben weil er läuft) -> die Suche nach einer Möglichkeit von außen dem Arbeitsspeicher beizukommen

http://paste.pocoo.org/show/74230/

Edit (BlackJack): Quelltext ausgelagert.

Verfasst: Freitag 20. Juni 2008, 13:47
von CM
Hoi,

vorweg: Bei soviel Code lieber hier hinein und dann verlinken. Außerdem hast Du recht viele Leerzeilen, die den Code aufblähen - ist aber natürlich Geschmackssache.

Also, dist_euclid ist ja nur eine Fließkommazahl. Die braucht nicht so furchtbar viel Speicher. Aber was steckt alles in 'entry'? Was sind das alles für Objekte? Und diese Objekte hängst Du zweimal an Listen an. Eine davon wird regelmäßig geleert, aber die andere läuft so lange voll, bis die Schleife zuende ist. Könnte es daran liegen?

Noch aus Neugierde: Du machst Molecular Docking? Welche Software nutzt Du denn da? ;-)

Gruß,
Christian

Verfasst: Freitag 20. Juni 2008, 14:30
von acidk
Kein Docking. Kraftfelder innerhalb einer Bindingsite berechnen; Eigenschaften des Liganden als Smarts berechnen und beides matchen. Für die Kraftfeldberechnungen nehme ich Grid -- sei froh, wenn Du es nicht kennst!

dist_euclid ist die Enfernungsberchnung zwischen Smart und Gridpunkt.
Entry enthält die Gridpunkt Information (Energie/x/y/z Koordinaten + Euclid Dist).

new_entry ist eine Liste aus Listen (Distanzen EINES Smarts auf dem Liganden zu ALLEN Grid Punkten)). Die kürzeste Distanz enspricht einem Matching. Die kürzeste Distanz kriege ich in Zeile 154. Punkt mit kleinster Distanz: s. 159.

List_2_check ist nur eine Kontroll Liste, die alle Distanzen enthält (um zu sehen, ob die richtigen Dimensionen = smarts* Gridspots vorhanden sind).

aber: Diese Liste wird doch wieder überschrieben, wenn ich die ganze Funktion innerhlb meiner for - i Schleife erneut aufrufe, oder?

Gruß, Florian

Verfasst: Freitag 20. Juni 2008, 15:24
von CM
acidk hat geschrieben:Kein Docking. Kraftfelder innerhalb einer Bindingsite berechnen; Eigenschaften des Liganden als Smarts berechnen und beides matchen. Für die Kraftfeldberechnungen nehme ich Grid -- sei froh, wenn Du es nicht kennst!

Ah, ok. Danke. Obwohl eigentlich wollte ich das auch mal testen; komme ich wohl nicht so schnell zu ...
acidk hat geschrieben: aber: Diese Liste wird doch wieder überschrieben, wenn ich die ganze Funktion innerhlb meiner for - i Schleife erneut aufrufe, oder?
Hm, entweder bin ich blind, oder: Du definierst list_2_check = [] und gehst dann in "for ligand in method_vector:" und dann wird diese Liste länger und länger. Jetzt weiß ich natürlich nicht, wie *groß* die darin enthaltenen Objekte sind (dahin zielte meine Frage), aber kommentiere doch einfach mal das "list_2_check.append(entry)" zweimal aus. Hilft es?

Und außerdem berechnest Du in der Schleife nur zwei Werte, hängst aber viel mehr Dinge an Deine Listen. Kannst Du auf diese anderen Werte nicht sonstwo zugreifen? Vielleicht wäre da ein dict hilfreich: d[key] = [dist_euclid, percentage], wobei key ein Schlüssel ist mit welchem Du die relevante "site" indentifizierst.

Gruß,
Christian

Verfasst: Freitag 20. Juni 2008, 16:22
von acidk
okay - list_2_check wird immer länger, aber wenn ich def matched points das zweite Mal (mit einer anderen Struktur) aufrufe (Aufruf erfolgt über for i Schleife im Hauptprogramm) müsste diese ja wieder überschrieben werden.

Anyway - ich habe die list_to_check und die Dimensionskontrollen (174 ff.) erstmal auskommentiert -- hat aber leider nichts gebracht.

Und - was mich noch viel mehr wundert: nachdem ich die Punktesets reduziert habe (alle Punkte mit Interaktion 0 -> aus der Liste entfernt), also wesentlich weniger zu berechnen ist, habe ich das gleiche Problem wieder.

Ich werde es mal mit dem Dict probieren, oder mal versuchen mir die Distanzen anders zu berechnen (Pycluster; Distanzmatrix.. keine Ahnung..)

Nur ein Dict muss ich ja auch irgendwie laden /handeln.... ist hier der Vorteil gegenüber einer Liste so groß?

Schönes WE!

Verfasst: Freitag 20. Juni 2008, 16:42
von CM
acidk hat geschrieben:okay - list_2_check wird immer länger, aber wenn ich def matched points das zweite Mal (mit einer anderen Struktur) aufrufe (Aufruf erfolgt über for i Schleife im Hauptprogramm) müsste diese ja wieder überschrieben werden.
Seltsam, aber dennoch: Brauchst Du list_2_check? Du kannst in Zeile 174 auch nach der Länge von new_entry oder new_entry_sorted fragen. Diese sollte identisch sein mit list_2_check.
acidk hat geschrieben:Anyway - ich habe die list_to_check und die Dimensionskontrollen (174 ff.) erstmal auskommentiert -- hat aber leider nichts gebracht.
Schade. Also ist das überhaupt nicht der Punkt. Vielleicht solltest Du mal alles auskommentieren außer der eigentlichen Berechnung. Wird der Speicher immer noch gefüllt?
acidk hat geschrieben:Und - was mich noch viel mehr wundert: nachdem ich die Punktesets reduziert habe (alle Punkte mit Interaktion 0 -> aus der Liste entfernt), also wesentlich weniger zu berechnen ist, habe ich das gleiche Problem wieder.
Hm, vielleicht hat Leonidas sofort den Finger in die richtige Wunde gelegt und es gibt ein Memory Leak ...
acidk hat geschrieben:Nur ein Dict muss ich ja auch irgendwie laden /handeln.... ist hier der Vorteil gegenüber einer Liste so groß?
Wahrscheinlich nicht bei dem was Du beschrieben hast. Mir ging es darum nicht so viel Ballast in den Listen mitzuschleppen, den Du erst mal nicht brauchst. Aber da liegt offenbar gar nicht das Problem.

Auch ein schönes WE.
Christian

Verfasst: Freitag 20. Juni 2008, 17:52
von BlackJack
@acidk: Vielleicht könntest Du die Funktion auch mal auf mehrere aufteilen. Die ist für meinen Geschmack entschieden zu lang. Viele Namen, die man Überblicken muss, wovon ein paar auch gar nicht verwendet werden. Unter anderem die Argumente `path_2_write_data` und `file_2_kont`. Wäre mal Zeit auf zu räumen und zu refaktorisieren.

`smart_list` liesse sich viel kürzer erstellen:

Code: Alles auswählen

    smart_list = [list(i)[0] for i in method.findall(mol)]
Analog geht das auch bei `vector_list` und `method_vector`. `smart_list` könnte man zu einem Generator-Ausdruck machen, und falls `mol` Indexzugriffe erlaubt, könnte man `vector_list` einsparen.

`str.strip()` tut nicht dass, was Du anscheinend denkst:

Code: Alles auswählen

In [6]: 'MyDeathMatched'.strip('Matched')
Out[6]: 'yD'
Die erste Schleife über `method_vector` tut entweder nichts, weil das `a` immer wieder an neue Objekte gebunden wird, aber später nicht mehr verwendet wird. Oder könnte es sein, dass dort in dem Objekt, dass an `molecule2` gebunden ist, Datenstrukturen aufgebaut werden? Wenn ja, werden die auch irgend wann wieder frei gegeben? Wo kommt der Name her, wenn nicht als Argument für die Funktion?

Der Name `i` für etwas anderes als ganze Zahlen, insbesondere in einer Schleife, ist für viele Programmierer extrem irreführend.

In der ``if``-Abfrage mit `global_min` wird in beiden Zweigen fast das gleiche gemacht, dass kann man alles heraus ziehen.

Code: Alles auswählen

            if global_min < 0:
                percentage = (site[0] / global_min) * 100
            else:
                percentage = 'Zero div error'
            entry = site[:4] + [dist_euclid, probe, percentage]
            list_2_check.append(entry)
            new_entry.append(entry)
Der Liste, die an `new_entry_sorted` gebunden wird, würde ich entweder keinen Namen geben, oder falls Python 2.5 verwendet wird, das `key`-Argument der `min()`-Funktion benutzen.

Code: Alles auswählen

        best_of_line = sorted(new_entry, key=getcount)[0]
        # oder
        best_of_line = min(new_entry, key=getcount)

Verfasst: Montag 23. Juni 2008, 08:38
von acidk
Vielen Dank für Eure Tipps!

Die erste Schleife über `method_vector` tut entweder nichts, weil das `a` immer wieder an neue Objekte gebunden wird, aber später nicht mehr verwendet wird. Oder könnte es sein, dass dort in dem Objekt, dass an `molecule2` gebunden ist, Datenstrukturen aufgebaut werden? Wenn ja, werden die auch irgend wann wieder frei gegeben? Wo kommt der Name her, wenn nicht als Argument für die Funktion?
Mit "a" werden tatsächlich immer wieder neue Objekte erzeugt - Atome auf dem Liganden - es wirdim Prinzip eine weitere Datei erzeugt.


... und Aufräumen ist vielleicht keine so schlechte Idee :?

Verfasst: Montag 23. Juni 2008, 13:57
von acidk
Problem gefunden ... aber leider nicht gelöst!

Nachdem ich jetzt alle Funktionen nacheinander abgeklopft habe ist der Schuldige gefunden: Matplotlib!! (die Distanzberechnung war an und für sich okay!).

Ich lasse mir in meiner plotting Funktion für jede Struktur (insgesamt sind s 85)
sechs Kurven plotten - die entsprechenden Werte habe ich vorher übergeben.

Relevanter Code ist der Folgende (wenn ich diesen ausklammere läuft das Programm sauber [und ohne steigenden Ram Verbrauch bis zum Ende durch])

Code: Alles auswählen

def plotting():
        max_x = 0
	min_x = global_min				
	max_y = len(list_2_write_matched_points)		
	min_y = 0			
	y_values = [i for i in range (1 ,max_y+1)]	
	
	## Plotting Performance -> relative Values
		
	max_x_relative = 0.0					#between 0 and 100 %
	min_x_relative = 1.0
	max_y = (len(list_2_write_matched_points))+1		
	min_y = 0
	y_values_relative = [i for i in range (1 ,max_y)]

# -> existing x-Values == matched_ spots	
		
	if len(x_values) > 0: 	
		
		print "\n"
		print "existing x-values "
		
		
		# absolute values
		
		
		plot(x_values, y_values, color)
		axis([min_x, max_x, min_y+1, max_y+1])		#y Axis starts with 1== first Hit! (not zero!)	
		xlabel('absolute Interaction Energy')
		ylabel('matched spots')	
		name_for_saving_absolute = output_name +"_absolute_plot"+".png"	
		place_2_save_absolute = path_2_write_data+name_for_saving_absolute
		savefig(place_2_save_absolute) 
		print "plot successfully saved!"
		close()
					
		# relative values			
								
		plot(x_values_relative, y_values_relative, color)
		axis([min_x_relative, max_x_relative, min_y+1, max_y+1])
		xlabel('relative Interaction Energy')
		ylabel('matched spots')	
		name_for_saving_relative = output_name +"_relative_plot_"+".png"	
		place_2_save_relative = path_2_write_data+name_for_saving_relative
		savefig(place_2_save_relative)
		close()	
		print "plots successfully saved!"
	
	else:	
		print "nothing _2_plot" 
	
		error_string = file_2_kont +"nothing to plot! -> no points matched"
		error_log.write(error_string)
		error_log.write("\n")
Ich habe keine Ahnung, warum das bisschen Plotten dermaßen Speicher zieht.
Hab ich einen Denkfehler gemacht / ist Matplotlib schlecht implementiert (was ich jetzt mal nicht glaube)/ gibt es Alternativen?

Besten Dank!

Verfasst: Montag 23. Juni 2008, 15:30
von acidk
Okay - ich habs endlich!!

Ich hatte noch eine alte Matplotlib via Synaptics installiert (0.87.7)- und das Teil
hat einen Memory leak :twisted: *bööööh!*

Da soll mal wer drauf kommen -

0.98 nachinstalliert und die Sonne geht auf! :D