2017-01-16 8 views
1

Ich habe eine große Anzahl von Datendateien und jede aus einer Datendatei geladenen Daten werden hunderte Male neu abgetastet und mit verschiedenen Methoden verarbeitet. Ich habe numpy verwendet, um dies zu tun. Was ich vor mir habe, ist der Speicherfehler nach dem Ausführen der Programme mehrere Stunden. Da jede Daten separat verarbeitet werden und die Ergebnisse in einer .mat Datei mit scipy.savemat gespeichert werden, denke ich, dass der Speicher von früheren Daten freigegeben werden kann, so dass ich del variable_name + gc.collect() verwendet, aber das funktioniert nicht. Dann habe ich multiprocessing Modul verwendet, wie in this post und this post vorgeschlagen, funktioniert es immer noch nicht.Wie effektiv Speicher in Python freigeben?

Hier sind meine Hauptcodes:

import scipy.io as scio 
import gc 
from multiprocessing import Pool 

def dataprocess_session: 
    i = -1 
    for f in file_lists: 
     i += 1 
     data = scio.loadmat(f) 
     ixs = data['rm_ix'] # resample indices 
     del data 
     gc.collect() 
     data = scio.loadmat('xd%d.mat'%i) # this is the data, and indices in "ixs" is used to resample subdata from this data 

     j = -1 
     mvs_ls_org = {} # preallocate results files as dictionaries, as required by scipy.savemat. 
     mvs_ls_norm = {} 
     mvs_ls_auto = {} 
     for ix in ixs: 
      j += 1 
      key = 'name%d'%j 
      X = resample_from_data(data,ix) 
      mvs_ls_org[key] = process(X) 

     scio.savemat('d%d_ls_org.mat'%i,mvs_ls_org) 
     del mvs_ls_org 
     gc.collect() 

     j = -1 
     for ix in ixs: 
      j += 1 
      key = 'name%d'%j 
      X = resample_from_data(data,ix) 
      X2 = scale(X.copy(), 'norm') 
      mvs_ls_norm[key] = process(X2) 

     scio.savemat('d%d_ls_norm.mat'%i,mvs_ls_norm) 
     del mvs_ls_norm 
     gc.collect() 

     j = -1 
     for ix in ixs: 
      j += 1 
      key = 'name%d'%j 
      X = resample_from_data(data,ix) 
      X2 = scale(X.copy(), 'auto') 
      mvs_ls_auto[key] = process(X2) 

     scio.savemat('d%d_ls_auto.mat'%i,mvs_ls_auto) 
     del mvs_ls_auto 
     gc.collect() 

     # use another method to process data 
     j = -1 
     mvs_fcm_org = {} # also preallocate variable for storing results 
     mvs_fcm_norm = {} 
     mvs_fcm_auto = {} 
     for ix in ixs: 
      j += 1 
      key = 'name%d'%j 
      X = resample_from_data(data['X'].copy(), ix) 
      dp, _ = process_2(X.copy()) 
      mvs_fcm_org[key] = dp 

     scio.savemat('d%d_fcm_org.mat'%i,mvs_fcm_org) 
     del mvs_fcm_org 
     gc.collect() 

     j = -1 
     for ix in ixs: 
      j += 1 
      key = 'name%d'%j 
      X = resample_from_data(data['X'].copy(), ix) 
      X2 = scale(X.copy(), 'norm') 
      dp, _ = process_2(X2.copy()) 
      mvs_fcm_norm[key] = dp 

     scio.savemat('d%d_fcm_norm.mat'%i,mvs_fcm_norm) 
     del mvs_fcm_norm 
     gc.collect() 

     j = -1 
     for ix in ixs: 
      j += 1 
      key = 'name%d'%j 
      X = resample_from_data(data['X'].copy(), ix) 
      X2 = scale(X.copy(), 'auto') 
      dp, _ = process_2(X2.copy()) 
      mvs_fcm_auto[key] = dp 

     scio.savemat('d%d_fcm_auto.mat'%i,mvs_fcm_auto) 
     del mvs_fcm_auto 
     gc.collect() 

Dies ist der erste Weg, die ich getan habe. Ich spaltete file_lists in 7 Teile und lief 7 Python-Bildschirme, da mein Computer 8 CPU-Kerne hat. Kein Problem in MATLAB, wenn ich auf diese Weise mache. Ich kombiniere die Iterationen nicht über ixs für jede Datenprozessmethode, weil der Speicherfehler auftreten kann, also lief ich resample_from_data und speicherte die Ergebnisse separat. Da der Speicher Fehler bestehen bleibt, habe ich Pool Klasse:

pool = Pool(processes=7) 
pool.map(dataprocess_session_2, file_lists) 

die die Iteration über file_lists parallelisiert mit Dateinamen in file_lists als Eingaben lief.

Alle Codes werden in openSuSE mit python 2.7.5, 8 cores CPU und 32G RAM ausgeführt. Ich habe top verwendet, um den verwendeten Speicher zu überwachen. Alle Matrizen sind nicht so groß und es ist in Ordnung, wenn ich irgendeine der geladenen Daten unter Verwendung aller Codes abspiele. Aber nach mehreren Iterationen über file_lists fällt der freie Speicher dramatisch. Ich bin sicher, dass dieses Phänomen nicht von den Daten selbst verursacht wird, da kein so großer Speicher verwendet werden sollte, selbst wenn die größte Datenmatrix verarbeitet wird. Daher vermutete ich, dass die oben beschriebenen Möglichkeiten, den Speicher freizugeben, der durch die Verarbeitung der vorherigen Daten sowie die Speicherung der Verarbeitungsergebnisse verwendet wurde, den Speicher nicht wirklich freigegeben haben.

Irgendwelche Vorschläge?

+0

Warum wurde ich downvoted? – Elkan

+0

Ich muss das wirklich selbst lesen, aber ich denke nicht, dass du die Hand des 'GC' auf diese Weise erzwingen kannst. Python verwendet die Referenzzählung, um zu entscheiden, ob Objekte gelöscht werden sollen. Daher entfernt 'gc.collect()' diese Objekte wahrscheinlich nicht sofort. Sie könnten mehr Hoffnung haben, wenn Sie jede dieser Schleifen in ihre eigenen Funktionen zerlegen würden, die die Daten nicht zurückgeben, aber Sie sollten dies nur als Hilfe nehmen, um weiter auf Python GC zu lesen, da ich gut dran sein könnte dieser Vorschlag. Hoffentlich kann jemand, der besser informiert ist, klären. – roganjosh

+0

Update zu Ihrem Vorschlag: Ich versuche jetzt, obwohl kein Fehler auftritt, aber nach dem Ausführen meiner Datensätze für diese zwei Tage, nur einige KB Speicher (im Vergleich zu 32G RAM meines PCs) freigelassen wird. Da die verarbeiteten Daten eine relativ geringe Größe haben, befürchte ich, dass die Speicherkapazität immer noch erschöpft ist. – Elkan

Antwort

-3

dies eine Hilfe sein kann, GC.Collect()

+1

"Ich denke, der von früheren Daten verwendete Speicher kann freigegeben werden, also habe ich del variable_name + gc.collect() verwendet, aber das funktioniert nicht." – roganjosh

0

die Sie del explizit automatisch, sobald die Schleife endet freigegeben Alle Variablen. Nachher denke ich nicht, dass sie dein Problem sind. Ich denke, es ist wahrscheinlicher, dass Ihre Maschine einfach nicht 7 Threads mit (im schlimmsten Fall) 7 gleichzeitig ausgeführten data = scio.loadmat(f) verarbeiten kann. Sie könnten versuchen, diesen Aufruf als kritischen Abschnitt mit Sperren zu markieren.

+0

Danke. Kannst du mehr darüber erklären?Es ist kein Problem, dass 7 Daten gleichzeitig in den Speicher geladen werden. Was bedeutet "Maschine kann nicht 7 Threads mit 7 gleichzeitig ausgeführten Daten verarbeiten = scio.loadmat (f)"? – Elkan

+0

Es sind nicht nur 7 Daten. Sie müssen über den schlimmsten Fall nachdenken, in dem alle Threads ihre maximale Speichermenge verwenden. Ich kann Ihnen nicht sagen, welche Objekte am größten werden, vielleicht können Sie sie profilieren (am besten im Single-Thread-Modus). –

+0

Ich verstehe. Ich habe MATLAB benutzt dieselben Arbeiten zu gleichen Datensätzen, aber verwendet verschiedene verarbeitete Methoden, die von 'Prozess' Funktion in meinem Python-Code angegeben wurde, noch mehr werden in den Speicher in MATLAB geladen, kein Fehler existiert nach dem Ausführen für Tage. Da meine Matrix nicht so groß ist und die zurückgegebenen "X" und "X2" die gleiche Größe wie die Originalmatrix haben, haben sie auch nach Iteration durch "ixs" noch einen großen freien Platz. Dies wird von "top" in Linux überwacht. Ich habe bemerkt, dass Python nach 'del' immer noch 'freie Listen' hält, aber ich habe keine effektive Lösung gefunden. Ich vermute also, ob ich etwas verpasst habe. – Elkan

Verwandte Themen