2015-05-28 23 views
7

Sono confuso con l'utilizzo della memoria di python per una funzione. Sto eseguendo una funzione in cui viene restituito un dataframe di panda (1161 X 240) e gli argomenti sono (bamfile, pandas.Dataframe (1161 X 50)).Allocazione di memoria per loop in python

Ora darò l'utilizzo della memoria da profiler:

Line # Mem usage Increment Line Contents 
================================================ 
    120 983.363 MiB 0.000 MiB @profile 
    121        def overlapping_peaks_distribution(bam_peak1, overlap_df): 
    122         ''' 
    123         Returns dataframe for tag count distribution for overlapping peaks within 500bp (+,-) from summit. 
    124         This function also considers the gene transcrition direction. 
    125         :param bam_peak1: 
    126         :param overlap_df: 
    127         :return: 
    128         ''' 
    129 983.363 MiB 0.000 MiB  import pandas as pd 
    130 983.363 MiB 0.000 MiB  import sys 
    131 983.363 MiB 0.000 MiB  peak_distribution_sample = pd.DataFrame() 
    132 983.363 MiB 0.000 MiB  print 'Process: Feature extraction from BAM started' 
    133 1783.645 MiB 800.281 MiB  for ind, row in overlap_df.iterrows(): 
    134 1782.582 MiB -1.062 MiB   sys.stdout.write("\rFeature extraction for peak:%d" % ind) 
    135 1782.582 MiB 0.000 MiB   sys.stdout.flush() 
    136 1782.582 MiB 0.000 MiB   chr = str(row['chr']) 
    137 1782.582 MiB 0.000 MiB   orientation = row['Next transcript strand'] 
    138 1782.582 MiB 0.000 MiB   middle = row['start'] + row['summit'] 
    139 1782.582 MiB 0.000 MiB   start = middle - 3000 
    140 1782.582 MiB 0.000 MiB   stop = start + 50 
    141 1782.582 MiB 0.000 MiB   list_sample1 = [] 
    142          #total_tags = int(bam_peak1.mapped) will get total no of mapped reads 
    143        
    144 1782.586 MiB 0.004 MiB   for i in range(0, 120): 
    145 1782.586 MiB 0.000 MiB    tags1 = bam_peak1.count(chr, start, stop) 
    146 1782.586 MiB 0.000 MiB    start = stop 
    147 1782.586 MiB 0.000 MiB    stop = start + 50 # divide peaks into length of 25 bp 
    148 1782.586 MiB 0.000 MiB    list_sample1.append(tags1) 
    149 1782.586 MiB 0.000 MiB   if orientation > 0: # Direction gene transcription 
    150           #print 'Towards 5 prime' 
    151 1780.883 MiB -1.703 MiB    peak_distribution_sample = peak_distribution_sample.append(pd.Series(list_sample1), ignore_index=True) 
    152          else: 
    153           #print 'Towards 3 prime' 
    154 1783.645 MiB 2.762 MiB    peak_distribution_sample = peak_distribution_sample.append(pd.Series(list_sample1[::-1]), ignore_index=True) 
    155         #print peak_distribution_sample 
    156 1783.645 MiB 0.000 MiB  return peak_distribution_sample 

Non capisco perché in linea 133 incrementa 800MB (folle). Questo sta divorando tutto lo spazio nella mia memoria. Non so che sia colpa mia?

Ho utilizzato il grafico degli oggetti per cercare le perdite di memoria. Numero dell'oggetto prima della funzione iniziato:

(Pdb) objgraph.show_most_common_types() 
function     15293 
tuple      4115 
dict      3086 
cell      2670 
list      2107 
weakref     1834 
wrapper_descriptor   1760 
builtin_function_or_method 1655 
getset_descriptor   1235 
type      1232 

Numero di oggetti dopo la funzione finito.

(Pdb) import objgraph 
(Pdb) objgraph.show_growth() 
function      16360  +1067 
dict       3546  +460 
list       2459  +354 
tuple       4414  +306 
getset_descriptor    1508  +273 
builtin_function_or_method  1895  +240 
weakref      2049  +215 
module       593  +123 
wrapper_descriptor    1877  +117 
type       1341  +109 

Possiamo vedere un aumento significativo degli oggetti. Ho anche prodotto un grafico. enter image description here

credo che la casella caratteri rossi supponiamo di essere liberato, ma non lo sono.

+2

È possibile che 'overlap_df.iterrows()' carichi interamente in memoria prima di iniziare la prima iterazione. – SuperBiasedMan

+0

https://github.com/pydata/pandas/issues/7683 –

+0

Questo potrebbe essere un problema, ma come liberare quella memoria. –

risposta

0

Sei sicuro che non stia mostrando la dimensione totale di overlap_df?

V'è la cosa analoga qui:

144 1782,586 MiB 0.004 MIB per i in range (0, 120):

Profiler mostra dimensione totale della lista di 120 numeri interi da 400 KB .

+0

Ciò significa che overlap_df ha una dimensione di 800 MB. Questo non è possibile perché nella memoria fisica occupa spazio di 8 MB. Ho letto che ad ogni iterazione alloca la memoria ma non la rilascia. Alla fine termina la funzione con la stampa out_of_memory(). Ho anche provato ** gc.collect() ** ma non ha effetto. i cicli annidati peggiorano le cose. –

0

Ho trovato la perdita di memoria. Era a causa di un modulo di terze parti (pysam) che presentava una perdita di memoria.