2017-09-03 72 views
3

我如何確定這段代碼是線程安全的?是python numpy數組操作+ =線程安全嗎?

import numpy as np 
from threading import Thread 

n_threads = 5 

ones = np.ones((5, 5)) 
A = np.ones((5, 5)) 

def my_function(): 
    global A 
    for i in range(250): 
     A += ones # is += thread safe ? 

threads = [Thread(target=my_function) for i in range(n_threads)] 

for t in threads: 
    t.start() 

for t in threads: 
    t.join() 

print(A) 

應該是一個關鍵的共享內存?令人驚訝的是,我總是得到相同的結果,並且數組的所有條目都具有相同的值。我希望的線程來更新矩陣的值,而對於一些丟失......

感謝。

+0

在我看來,它是不是安全的,即使在一個線程。當陣列具有「多」行(無論「多」的意思),它們經常更新的數據塊,因此,如果如果你做'A + = A [0]'的'一個[0],當您去'可能會改變。 – DyZ

+1

@DYZ:他們實際上爲[1.13]中的操作引入了定義的語義(https://docs.scipy.org/doc/numpy-1.13.0/release.html#ufunc-behavior-for-overlapping-inputs) ,最新的版本。 – user2357112

+1

雖然GIL確實提供了這樣的CPython的操作一定程度的保護,仍有一些失敗的情況下,和其他Python實現(其中一些確實有對NumPy的一定程度的支持),可以做到無鎖定或細粒度鎖定。 – user2357112

回答

0

你的代碼是不是安全的。一些NumPy ufuncs(像你隱式使用的add())可以釋放GIL。可能你在玩具例子中從未看到任何問題的原因是它運行時間很短,數據量也很小。你也可以通過簡單的計算來避免問題,但我想你的真實代碼更復雜。

總之,你不能做你的多線程做什麼,沒有鎖定。鎖定可能會挫敗多線程代碼的目的。

+0

當然,你是對的。我已經將矩陣大小增加到了1000,並且有1000次迭代,問題出現了。謝謝! –