4

現在、 globalLock = threading.Lock()があり、次の呼び出しを行います。

Parallel(n_jobs=2)(delayed(serialRemove)(dir,c,b,l,f) for f in os.listdir(dir))

jobLib を使用します。でserialRemove、私は持っています

Lock.acquire()
print(f+' begin')
if h in hashes:
    try:
        os.remove(path)
        if l: print('Removing ' + path)
        removed += 1
    except os.error:
        print('Encountered error removing file') 
else:
    hashes.add(h)
print(f+' end')
Lock.release()

呼び出しの一部は次のようになります:
10.txt begin
11.txt begin
20.txt begin
コードを Lock で囲むと、begin が 2 つ表示される理由がわかりません。コード ブロックを保護する簡単な方法はありますか? 理想的には、次 の よう に
なり ます 。





4

1 に答える 1

5

threading.Lock同じプロセスのスレッド間でのみ機能します。

ここで並列処理に使用しているライブラリを実際に知らなければ、確認するのは困難ですが、ほぼ確実に、別々のプロセスでタスクを実行しています。(少なくともCPythonを使用して、同じプロセスでスレッドを開始するものはすべて、GILのため、CPUバウンドコードに対して効果的な並列処理を取得しません。したがって、それらのいずれもそれを実行しません。)

したがって、threading.Lock他のプロセスのグローバルオブジェクトを使用しようとすると、各プロセスで完全に独立したロックが取得されます。したがって、ロックしても効果はありません。(一部の並列ライブラリ(プラットフォームごとに異なる可能性があります)では、代わりにエラーが発生します。ただし、必要な処理を実行できる方法はありません。)

ほとんどの並列化ライブラリには、マルチプロセッシングのスタイルで機能する独自のロックタイプがあります。使用している場合は、ライブラリに付属しているものを使用してください。

そうでない場合は、ライブラリの動作によっては、multiprocessing.Lockうまくいく可能性があります。

flockそうでない場合は、たとえばロックファイルを使用して明示的に何かを実装する必要があります(おそらく/と一緒にlockf、またはWindowsの排他的オープンなどに依存します)。

また、コードの例の行を理解できるAPIを備えた複数のライブラリの少なくとも1つ[ joblib]は、共有のないタスク用に明示的に設計されているため、まったくロックします。(multiprocessing.Lockとにかく動作する可能性がありますが、実際にはそれを当てにするべきではありません。)

于 2013-01-10T23:27:50.720 に答える