2014-02-27 102 views
1

以下是使用python進行多處理的示例程序。我發現每個進程的內存使用量比每個進程應該使用的內存高出2到3倍。如果我只用一個進程來計算,所用的內存就會多1.3倍,並且隨着進程數量的增加而增加。Python多處理內存管理多維數組上的循環

例如,對於帶有float64的1000 * 1000 * 1000的數組,它應該使用8Gb的內存,但我看到內存高達25Gb,並行運行8個處理器!但我讀過多處理使用共享內存。所以我不確定內存在哪裏泄漏。這裏是代碼:

#To use the code, please take care of your RAM. 
#If you have higher RAM, kindly try for the bigger arrays to see the difference clearly. 

from numpy import * 
import multiprocessing as mp 

a = arange(0, 2500, 5) 
b = arange(0, 2500, 5) 
c = arange(0, 2500, 5) 
a0 = 540. #random values 
b0 = 26. 
c0 = 826. 
def rand_function(a, b, c, a0, b0, c0): 
    Nloop = 100. 
    def loop(Nloop, out): 
     res_total = zeros((500, 500, 500), dtype = 'float') 
     n = 1 
     while n <= Nloop: 
      rad = sqrt((a-a0)**2 + (b-b0)**2 + (c-c0)**2) 
      res_total = res_total + rad 
      n +=1 
     out.put(res_total) 
    out = mp.Queue() 
    jobs = [] 
    Nprocs = mp.cpu_count() 
    print "No. of processors : ", Nprocs 
    for i in range(Nprocs): 
     p = mp.Process(target = loop, args=(Nloop/Nprocs, out)) 
     jobs.append(p) 
     p.start() 

    final_result = zeros((500,500,500), dtype = 'float') 

    for i in range(Nprocs): 
     final_result = final_result + out.get() 

    p.join() 
test = rand_function(a,b,c,a0, b0, c0) 

任何人都可以請告訴我哪裏的內存泄漏?以及如何克服?非常感謝你提前。

+1

您認爲這是「應該使用」多少?爲什麼? –

+0

例如,對於1000 * 1000 * 1000的數組,應該爲float64使用(1000 * 1000 * 1000 * 8)/(1024 ** 3)Gb的內存。對?我也通過給出一個.nbytes來驗證,你會知道使用的內存。 – geekygeek

+0

Just jound this:included into Python 3.4 [tracemalloc](http://docs.python.org/3.4/library/tracemalloc.html) – User

回答

2

使用存儲器(的很多)有些東西:

  1. res_total
  2. res_total = res_total + rad右手側創建臨時數組,對於一個時刻,res_total同時存在。使用+=可以避免這種情況。
  3. out.put(res_total)泡菜陣列,使用大致相同的內存量。

這應該解釋爲什麼內存使用可以遠高於1。

+0

謝謝! 2.完成。但是3,有沒有辦法來克服'out.put(u_total)'酸洗? – geekygeek

+2

@geekygeek您可以嘗試避免隊列中的大數據和[在共享內存中使用numpy數組進行多處理](http://stackoverflow.com/q/7894791/222914)。 –

+0

謝謝!有沒有一種方法可以避免使用零數組初始化'res_total'或'final_result'?因爲這也有助於增加內存。 – geekygeek

1

在一個不相關的說明中,如果您想要做的是並行處理大量數組,最好使用multiprocessing.Pool,這樣您就不必親自處理循環的輸出值。此外,您的代碼不會將相同的任務分配給所有不同的工作進程,我不確定這是否是有意的。

import numpy as np 
import multiprocessing as mp 


def loop(arg): 
    max_n, a, b, c, a0, b0, c0 = arg 
    res_total = np.zeros(shape, dtype=np.float) 
    print 'starting' 
    for _ in range(max_n): 
     rad = np.sqrt((a - a0) ** 2 + (b - b0) ** 2 + (c - c0) ** 2) 
     res_total = res_total + rad 
    print 'done' 
    return res_total 


def rand_function(a, b, c, a0, b0, c0): 
    c_cpu = mp.cpu_count() 
    n_loop = 10 
    print "No. of processors : ", c_cpu 
    pool = mp.Pool(c_cpu) 
    out = pool.map(loop, [(n_loop/c_cpu, a, b, c, a0, b0, c0) 
          for _ in range(c_cpu)]) 

    print 'collating' 
    final_result = np.zeros(shape, dtype='float') 
    for i in out: 
     final_result += i 
    print final_result.shape 


shape = (50, 50, 50) 
rand_function(np.arange(0, 250, 5), np.arange(0, 250, 5), 
        np.arange(0, 250, 5), 540, 26, 826) 

在我的機器周圍的內存技嘉每個工作進程的用戶。您的原始代碼每個工作人員使用1.4GB左右(然後增長到2GB)。我懷疑這與輸出隊列被修改有關,這會觸發操作系統的寫時複製(儘管我不確定)。

+0

我看到multiprocessing.Pool使用比multiprocessing.Process更多的內存。對於較小的陣列,您看不到太多差異。如果我使用'multiprocessing.Pool'運行上述解決方案,就像您爲500 * 500 * 500的數組所提供的那樣,我會看到內存達到18Gb。而'multiprocessing.Process'則達到12Gb,這仍然很高。 – geekygeek