2010-09-22 66 views
12

我有一張640x480圖片的numpy.array,每張圖片長630張。 總陣列因此是630x480x640。 我想要生成一幅平均圖像,並且計算所有630張圖像上每個像素的標準偏差 。Python多處理Pool.map正在調用aquire?

這是很容易

avg_image = numpy.mean(img_array, axis=0) 
std_image = numpy.std(img_array, axis=0) 

完成然而,因爲我跑這50個左右這樣的陣列,並有 8核/ 16線程工作站,我想我會得到貪婪使用 multiprocessing.Pool並行化。

所以我做了以下內容:

def chunk_avg_map(chunk): 
    #do the processing 
    sig_avg = numpy.mean(chunk, axis=0) 
    sig_std = numpy.std(chunk, axis=0) 
    return([sig_avg, sig_std]) 

def chunk_avg(img_data): 

    #take each row of the image 
    chunks = [img_data[:,i,:] for i in range(len(img_data[0]))] 

    pool = multiprocessing.Pool() 
    result = pool.map(chunk_avg_map, chunks) 
    pool.close() 
    pool.join() 
    return result 

但是,我看到的只是一個小的加速。通過將打印語句放在chunk_avg_map中,我可以確定一次只能啓動一個或兩個進程,而不是我所期望的那樣。

然後,我跑到通過CPROFILE我的代碼在IPython中:

%prun current_image_anal.main() 

結果表明,目前大部分時間在電話都花在收購:

ncalls tottime percall cumtime percall filename:lineno(function) 
    1527 309.755 0.203 309.755 0.203 {built-in method acquire} 

我的理解是什麼與鎖定有關,但我不明白爲什麼我的代碼會這樣做。有沒有人有任何想法?

[編輯]根據要求,這是一個可運行的腳本,它演示了這個問題。 你可以通過任何你喜歡的方式來分析它,但是當我發現獅子 份額的時間已被調用獲取,而不是像我想 預期的那樣。

#!/usr/bin/python 
import numpy 
import multiprocessing 

def main(): 
    fake_images = numpy.random.randint(0,2**14,(630,480,640)) 
    chunk_avg(fake_images) 

def chunk_avg_map(chunk): 
    #do the processing 
    sig_avg = numpy.mean(chunk, axis=0) 
    sig_std = numpy.std(chunk, axis=0) 
    return([sig_avg, sig_std]) 

def chunk_avg(img_data): 

    #take each row of the image 
    chunks = [img_data[:,i,:] for i in range(len(img_data[0]))] 

    pool = multiprocessing.Pool() 
    result = pool.map(chunk_avg_map, chunks) 
    pool.close() 
    pool.join() 
    return result 

if __name__ == "__main__": 
    main() 
+0

什麼給你multiprocessing.cpu_count()?如預期的那樣, – 2010-09-22 17:26:05

+0

multiprocessing.cpu_count()產生16。 – 2010-09-22 17:48:04

+0

這可能沒關係,但是'chunk_avg(im_data)'是'chunk_avg(img_data)'? – unutbu 2010-09-22 17:58:06

回答

7

我相信問題是,CPU花費的時間來處理每塊中的量相對於所花費的時間與輸入和輸出複製到和來自工作進程的量小。我修改了示例代碼,將輸出分爲16個塊,並打印出在運行chunk_avg_map()開始和結束時的CPU時間差異(time.clock())。在我的系統上,每個單獨的運行在CPU時間的一秒鐘內略微下降,但進程組(系統+用戶時間)的整體CPU時間使用超過38秒。每塊大約0.75秒的複製開銷使得您的程序執行計算的速度僅略快於multiprocessing可以傳遞數據,從而導致只有兩個工作進程被同時使用。

如果我修改代碼,使「輸入數據」只是xrange(16)並在chunk_avg_map()內構建隨機數組,然後我看到sysem +用戶時間下降到大約19秒,並且所有16個工作進程同時執行。