簡體   English   中英

Python:多處理池內存泄漏

[英]Python: multiprocessing pool memory leak

我有一系列的時間課程是8640 x 400。
編輯:第0個昏暗處是位置,第1個昏暗處是該位置的時間進程。

我需要計算每個點的交叉光譜相干性,這些都可以獨立完成。

因此,我開始嘗試使用多處理模塊:

from multiprocessing import Pool
import numpy as np    
from matplotlib.mlab import cohere
from itertools import product    
from scipy.signal import detrend

# this is a module of classes that I wrote myself
from MyTools import SignalProcessingTools as sig

def compute_coherence(args):
    rowA = roi[args[0], :]
    rowB = roi[args[1], :]
    coh, _ =  cohere(rowA, rowB, NFFT=64, Fs=sample_rate, noverlap=32, sides='onesided')
    #TODO: use the freq return and only average the freq in particular range...

    return  np.sqrt(coh.mean())

### start here ###
# I detrend the data for linear features
roi = detrend(data=roi, axis=1, type='linear')
# and normalize it to std. Very simple method, uses x.std() in a loop 
roi = sig.normalize_std(roi)

roi = np.random.rand(8640, 386)# in reality this is a load from disk
length = roi.shape[0]
indices = np.arange(length)
# this gives me all combinations of indices i and j
# since I want the cross spectral coherence of the array
args = product(indices, indices) # note, args is an interator obj

pool = Pool(processes=20)
coh = pool.map(compute_coherence,  args)

該程序使用了20 GB以上的內存,我看不到明顯的內存泄漏。 Google有很多關於該主題的回報,但我真的不太了解如何找到答案。

編輯:大錯誤... roi數組不是8640x8640x400,它只有8640 x 400對不起...:| 漫長的一天

也許我錯過了一個錯誤...?

謝謝您的事先想法...

[更新]因此,在修改代碼並處理掉注釋部分之后,我相信我已將內存問題縮小為cohere()方法。 運行代碼並僅返回零數組可以正常工作。

這是更新的版本:

from os import path, getenv
import numpy as np
from matplotlib import mlab
import scipy.signal as sig
from multiprocessing import Pool
from itertools import product
import Tools
from scipy.signal import detrend

from pympler import tracker
tr = tracker.SummaryTracker()
import gc


def call_back():
    gc.collect()

def call_compute(arg):
    start, stop = arg
    ind_pairs = indice_combos[start:stop]
    coh = np.zeros(len(ind_pairs), dtype=float)

    #tr.print_diff()

    for i, ind in enumerate(ind_pairs):
        row1 = ind[0]
        row2 = ind[1]

        mag, _ = mlab.cohere(roi[row1,:], roi[row2,:], NFFT=128, Fs=sample_rate, noverlap=64, sides='onesided')

        coh[i] = np.sqrt(mag.mean()) 
        #tr.print_diff()

    #tr.print_diff()    
    return coh

### start Here ###
imagetools = Tools.ImageTools()
sigtools = Tools.SignalProcess()

HOME = Tools.HOME
sample_rate = 1 / 1.65

mask_obj = imagetools.load_image(path.join(HOME, 'python_conn/Rat/Inputs/rat_gm_rs.nii.gz'))
mask_data = mask_obj.get_data()

rs_obj = imagetools.load_image(path.join(HOME, 'python_conn/Rat/Inputs/rs_4D.nii.gz'))
rs_data = rs_obj.get_data()

# logical index
ind = mask_data > 0 
roi = rs_data[ind, :]

# normalize with STD
roi = sigtools.normalize_nd(roi)
# detrend linear
roi = detrend(data=roi, axis=1, type='linear')
# filter
roi = sigtools.butter_bandpass(lowcut=0.002, highcut=0.1, sample_rate=sample_rate, data=roi, order=5)

# drop frames for steady state and filter noise
roi = roi[:, 16:] 

################
### testing ####
roi = roi[0:5000,:]
################
################

length = roi.shape[0]    

# setup up row and col vector of indices
indices = np.arange(length)
temp = product(indices, indices)# all possible combinations iterator
indice_combos = [ i for i in temp ] # make iterator into a list

num_cores = 10
chunk_size = len(indice_combos) / num_cores  # divdide the combo list for each core
grps = np.arange(0, len(indice_combos)+chunk_size, chunk_size)

#make the final list of args, where each item is a pair of stop and stop
args = [ [grps[i], grps[i+1]-1]  for i in range(0, len(grps)-1)]
args[-1][1] = args[-1][1] + 1

# deallocate some memory
grps = None

# Multi core
pool = Pool(num_cores)
coh = np.hstack(pool.map(call_compute, args, call_back()))

coh = coh.ravel()

out_path = path.join(HOME, 'python_conn/Rat/coh.npy')
np.save(out_path, coh)

map = np.zeros_like(mask_data)
map[ind] = coh.sum(0)

out_path = path.join(HOME, 'python_conn/Rat/coherence_map.nii.gz')
imagetools.save_new_image(map, out_path, rs_obj.coordmap)

[更新]

這不是cohere的錯...我的壞...我希望開發人員不會看到此...:| 我做了很多修改。 因此,恐怕此線程不再有效。

有什么幫助:

僅使用迭代器

發送多個I,j對進行處理

有很多開銷,但內存實際上並沒有增加那么多。 我覺得自己有點兒濫用了...但是當您學習新東西時,在這里總是很難精確...我很驚訝沒有人討厭我。 明天我將發布自己的解決方案。

這些數字不累加。 正如@sashkello所指出的,您有一個包含29,859,840,000個元素的數組。 即使它們每個僅占用1個字節,您也將使用30 GB,而不是20 GB。那么,您沒有揭示什么? ;-)

后來:現在8640 * 400 = 3,456,000-那么“ 7,500萬個元素”從何而來? 7500萬將接近8640 * 8640。

無論如何,有兩件事需要調查:

  1. 如果不調用多處理機制,而僅在主程序中執行一個塊,它將消耗多少內存?

  2. 叉積( args )有多大? 由於您似乎對數組的大小仍然感到困惑,因此無法從這里猜測。

我們還需要知道另一件事:池中有多少個進程? Plain Pool()意味着“使用所有可用的”處理器,但無法猜測您有多少個。 當然,每一個內存使用量都會增加。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM