0

multiprocessing ライブラリの Process モジュールを使用して、パフォーマンスを向上させるためにコードをスレッド化しようとしています。

コードの骨組みは、作業対象のスレッドごとに辞書を作成することです。すべての処理が完了すると、辞書が合計されてファイルに保存されます。リソースは次のように作成されます。

histos = {}
for int i in range(number_of_threads):
    histos[i] = {}
    histos[i]['all'] =      ROOT.TH1F objects
    histos[i]['kinds_of'] = ROOT.TH1F objects
    histos[i]['keys'] =     ROOT.TH1F objects

次に、プロセス内で、各スレッドが独自の histos[thread_number] オブジェクトを使用して、含まれている ROOT.TH1Fs を処理します。ただし、私の問題は、どうやら次のように Process でスレッドを開始した場合です。

proc = {}
for i in range(Nthreads):
    it0 = 0 + i * n_entries / Nthreads  # just dividing up the workload
    it1 = 0 + (i+1) * n_entries / Nthreads 
    proc[i] = Process(target=RecoAndRecoFix, args=(i, it0, it1, ch,histos)) 
    # args: i is the thread id (index), it0 and it1 are indices for the workload,
    # ch is a variable that is read-only, and histos is what we defined before, 
    # and the contained TH1Fs are what the threads put their output into.
    # The RecoAndFix function works inside with histos[i], thus only accessing
    # the ROOT.TH1F objects that are unique to it. Each thread works with its own histos[i] object.
    proc[i].start()

スレッドは histos[i] オブジェクトにアクセスできますが、それらに書き込むことはできません。正確には、TH1F ヒストグラムで Fill() を呼び出すと、オブジェクトは共有変数ではないため、オブジェクトに書き込むことができないため、データは入力されません。

だからここ:https://docs.python.org/3/library/multiprocessing.html 代わりに multiprocessing.Array() を使用して、スレッドによる読み取りと書き込みの両方が可能な配列を作成する必要があることがわかりました。このような:

typecoder = {}
histos = Array(typecoder,number_of_threads)
for int i in range(number_of_threads):
    histos[i] = {}
    histos[i]['all'] =      ROOT.TH1F objects
    histos[i]['kinds_of'] = ROOT.TH1F objects
    histos[i]['keys'] =     ROOT.TH1F objects

ただし、辞書を型として受け入れません。それは動作しません、それは TypeError: unhashable type: 'dict' と言います

では、この問題を解決するための最良のアプローチは何でしょうか? 私が必要とするのは、辞書に格納されているすべての「すべての種類のキー」のインスタンスを各スレッドに渡すことです。これにより、それらは独自に機能します。そして、これらの受信したリソースを書き込むことができなければなりません。

助けてくれてありがとう、そして些細なことを見落としていたらごめんなさい、私は以前にスレッド化されたコードをしましたが、まだpythonではしていません。

4

2 に答える 2

1

欠けている部分は、「プロセス」と「スレッド」の違いです。投稿でそれらを混在させますが、アプローチはスレッドでのみ機能し、プロセスでは機能しません。

スレッドはすべてメモリを共有します。それらはすべて同じ辞書を参照するため、それを使用して相互に通信したり、親と通信したりできます。

プロセスには個別のメモリがあります。それぞれが独自の辞書のコピーを取得します。通信したい場合は、他の手段 (たとえば、を使用multiprocessing.Queue) で通信する必要があります。一方、これは彼らが分離の安全を得ることを意味します。

Python でさらに複雑になるのは「GIL」です。スレッドはほとんどの場合、同じ Python インタープリターをシリアルに共有し、I/O を実行するとき、ネットワークにアクセスするとき、またはそれを特別に準備するいくつかのライブラリ (numpy、画像処理、その他のいくつか) を使用してのみ並列で実行します。一方、プロセスは完全な並列処理を取得します。

于 2021-04-12T13:13:47.303 に答える
0

Python マルチプロセッシング モジュールには、スレッドとプロセス間で共有できる辞書を提供するマネージャー クラスがあります。

例については、ドキュメントを参照してください: https://docs.python.org/3/library/multiprocessing.html#sharing-state-between-processes

于 2021-04-12T13:40:23.497 に答える