2011-04-13 70 views
0

我想在Python中使用多個線程來計算圖像的像素值,以便在最後構建,儘管我很難弄清楚如何獲取線程的結果並收集。這裏的設置:如何從Python中的多個線程中收集數據?

創建一個Queue.Queue()對象,以及一個threading.Thread()類孩子:

q = Queue.Queue() 
class myThread(threading.Thread): 
    def __init__(self, queue): 
    self.queue = queue 
    threading.Thread.__init__(self) 
    def run(self): 
    while True: # loop forever 
     task = self.queue.get() 
     rs = self.do_work(task) # I've got the result; now what to do with it? 
     self.queue.task_done() 

的想法是,我要收集像素數據爲500×500的圖像,這是最初的名單250000(500×500)的元件,這將最終將與PIL製作成一個圖像:

pixels = array.array('B', pixels).tostring() 
im = Image.fromstring('L', size, pixels) 
im.show() 

所以我填充隊列具有用於每個像素的任務,並生成線程池:

for i in range(5): 
    t = myThread(q) 
    t.setDaemon(True) 
    t.start() 
for y in range(500): 
    for x in range(500): 
    q.put({'x':x, 'y':y}) 
q.join() 

那麼如何獲取數據全部收集?我認爲將250,000元素列表傳遞給每個線程是個壞主意,因爲要傳遞數據數組的大小,並且因爲每個線程都會丟失來自其他線程的數據。

編輯: 對於那些你想知道它是否是值得的,在所有爲此在一個多線程的方式,這是正在做計算圖像座標有幾個Perlin雜點功能的工作。它生成一個perlin二維噪聲點(一個5x5網格),再加上幾個八度(10x10,20x20和40x40網格),並計算這些點之間的像素值。因此,對於最終圖像中的每個像素,必須對每個八度音程執行三次數學運算(給定點周圍的平均X點,給定點周圍的平均Y點以及平均值),然後在八度音階結果之間進行加權平均。

在我的8核心Mac上,我看到Python進程在運行時使用1個線程和100%的處理器。雖然我知道我有8個內核,並且看到進程表示400-600%的處理器用於顯示他們正在利用其他內核,我只是希望這個Python腳本可以做到這一點。

+1

由於GIL,在純Python的不同線程中執行CPU密集型工作毫無意義。 – jfs 2011-04-13 19:46:54

+1

你在使用IronPython嗎?如果不是,那麼跨線程分割計算密集型任務的意義不大;作爲J.F.塞巴斯蒂安提到,標準的Python解釋器實際上不會讓你同時運行這些線程。 – phooji 2011-04-13 20:23:42

+0

我編輯我的問題,以表明我實際上每像素在做什麼;這是否構成高CPU任務?如果運行它的機器是多核而不是超線程,它會有什麼區別嗎? – MidnightLightning 2011-04-14 13:45:58

回答

2

Python擁有修改python級別數據結構的全局鎖,稱爲GIL。這使得很難有效地完成你想要用線程做的事情。

但是,絕望不!善良的開發者給了我們多處理模塊。將多線程替換爲多線程(以使用multiprocessing.Process和multiprocessing.Queue),並且您的應用程序是多進程應用程序。

至於你的問題,你想要另一個隊列,在另一個方向。

+0

謝謝!我會看看'multiprocessing'模塊;通過文檔在我的巡視中錯過了一個。 – MidnightLightning 2011-04-14 13:39:47

0

我會有一個全局列表,可以被每個線程訪問。我確實有這樣的情況,沒有問題就這樣做了。

1

我想你應該使用兩個隊列。

一個用於作業/任務,一個用於輸出。

任務完成後,將結果放在輸出隊列中。