2011-12-21 11 views
2

threadingとscipy.stats.randintモジュールを使用する際に問題があります。実際、いくつかのスレッドが起動されると、起動されたすべてのスレッドでローカル配列(以下のコードのbootIndexs)が使用されているようです。Pythonでスレッディングする:ローカル変数に問題がある

これは、発生したエラー

> Exception in thread Thread-559: 
Traceback (most recent call last): 
... 
    File "..\calculDomaine3.py", line 223, in bootThread 
    result = bootstrap(nbB, distMod) 
    File "...\calculDomaine3.py", line 207, in bootstrap 
    bootIndexs = spstats.randint.rvs(0, nbTirages-1, size = nbTirages) 
    File "C:\Python27\lib\site-packages\scipy\stats\distributions.py", line 5014, in rvs 
    return super(rv_discrete, self).rvs(*args, **kwargs) 
    File "C:\Python27\lib\site-packages\scipy\stats\distributions.py", line 582, in rvs 
    vals = reshape(vals, size) 
    File "C:\Python27\lib\site-packages\numpy\core\fromnumeric.py", line 171, in reshape 
    return reshape(newshape, order=order) 
ValueError: total size of new array must be unchanged 

であり、これは私のコードです:あなたの答えのための

import threading 
import Queue 
from scipy import stats as spstats 

nbThreads = 4 

def test(nbBoots, nbTirages, modules): 

    def bootstrap(nbBootsThread, distribModules) : 

     distribMax = []    

     for j in range(nbBootsThread): 
      bootIndexs = spstats.randint.rvs(0, nbTirages-1, size = nbTirages) 
      boot = [distribModules[i] for i in bootIndexs] 

      distribMax.append(max(boot)) 

     return distribMax 

    q = Queue.Queue() 

    def bootThread (nbB, distMod): 
     result = bootstrap(nbB, distMod) 
     q.put(result, False) 
     q.task_done() 

    works = [] 

    for i in range(nbThreads) :  
     works.append(threading.Thread(target = bootThread, args = (nbBoots//nbThreads, modules[:],))) 


    for w in works: 
     w.daemon = True 
     w.start() 

    q.join() 

     distMaxResult = [] 

     for j in range(q.qsize()): 
      distMaxResult += q.get() 

     return distMaxResult 

class classTest: 
    def __init__(self): 
     self.launch() 

    def launch(self): 
     print test(100, 1000, range(1000)) 

感謝。

+0

あなたのコードでは、動作を説明するものは何も表示されません。実行して実験することができる自己完結型の例を考え出すことができますか? – NPE

+0

私はそれを編集します。scipyを持っているなら、このように使うことができます – user1062526

+0

(nbThreadsを 'nbThreads'に変更してしまえば)コードを実行でき、別のエラーが出ます(' Thread- 4(通訳者のシャットダウン中に発生する可能性が高い) ')。 – NPE

答えて

2

実際、いくつかのスレッドが起動されると、起動されたすべてのスレッドでローカル配列(以下のコードではbootIndexs)が使用されているようです。

これは、スレッドの全体的なポイントです。軽量なタスクは、すべてのプロセスを生成するプロセスを共有します。 :)シェア・ニア・ソリューションをお探しの場合は、おそらくmultiprocessing moduleを見てください。(ただし、スレッドを生成するよりも、システムの処理が重くなることに注意してください)。

しかし、戻ってあなたの問題に...鉱山は暗闇の中でのショットよりも少しですが、あなたは、この行を変更しようとすることができます:

boot = [distribModules[i] for i in bootIndexs] 

に:

boot = [distribModules[i] for i in bootIndexs.copy()] 

(配列自体ではなく配列のコピーを使用します)。これは問題ではないようです(実際には配列を反復していますが、実際には使用していません)が、スレッド内で使用するとわかります。

配列の内容は、それを操作するスレッドによって変更されることはありません。 「グローバル」配列の値を変更することが正しい動作である場合は、逆にそのリソースへの同時アクセスを禁止するためにLock()を実装する必要があります。あなたのスレッドは、次にような何か必要があります。

lock.acquire() 
# Manipulate the array content here 
lock.release() 
+0

私はコピーを試みますが、それは同じです。私は問題がアレイが作成されたときであると思う(上の行のscipyで)。この配列はおそらくスレッドと別のスレッドで作成され、同時に起動され、同じ配列以外の配列を作成しようとします...マルチプロセッサはPythonのウィンドウ上では難しいですが、私は感じています... – user1062526

+0

@ user1062526 - 断続的にエラーが発生するという事実は、それが競争条件に関連するエラーであるという明確な兆候です。 'bootIndex'は関数内でのみ参照されるので、配列にはさまざまなスレッドがアクセスするので、そのスコープは明白にローカルでなければなりません...:/ – mac

1

を私はスレッドとの経験がないので、これは完全に的外れかもしれません。

scipy.stats.randintは、scipy.statsの他のディストリビューションと同様に、対応する配布クラスのインスタンスです。これは、すべてのスレッドが同じインスタンスにアクセスしていることを意味します。 rvsコール中に、属性_sizeが設定されます。その間に異なるサイズの別のスレッドがインスタンスにアクセスすると、サイズが変更されていないValueErrorが返されます。これは私にとって競争状態のように聞こえる。

私は

numpy.random.randint(min, max, self._size) 

多分あなたがより良い運を持っている(これはscipy.stats.randintで呼び出している)、この場合には、直接numpy.randomを使用することをお勧めします。

numpy.randomで利用できないディストリビューションが必要な場合は、私の推測が正しい場合は、各スレッドでディストリビューションの新しいインスタンスをインスタンス化する必要があります。

+0

確かに、私は時には他の配布を必要とします。 ..良い方法は、私は、それは各スレッドのローカル変数をインスタンス化することだと思う...しかし、私はsuccedしませんでした。私はthreading.localsを試していますが、bootIndexsのargsに空の配列を渡そうとしますが、何も動作しません。 – user1062526

+0

異なるスレッドでspstats.randint(またはその他のscipy.statsディストリビューション)を使用する場合でも、それらは引き続きscipy.stats内の同じインスタンスを参照します。 – user333700

関連する問題