2017-09-03 11 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

私の意見では、1つのスレッド内であっても安全ではありません。配列に "多くの"行がある場合は、ブロック単位で更新されることが多いため、 'a + = a [0]'を実行すると 'a [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回に増やして、問題が浮かび上がった。ありがとう! –