0

渡された辞書を変更する関数を作成しました。ただし、マルチプロセッシング モジュールを使用してコードを並列化すると、シリアルで実行した場合とは異なる動作を示します。ディクショナリは変更されません。

以下に添付されているのは、私の問題のおもちゃの例です。map_async を使用して実行するとディクショナリは変更されませんが、for ループで実行すると変更されます。私の混乱を明確にしてくれてありがとう!

#!/usr/bin/env python

from multiprocessing import Pool

def main1(x):
  x['a'] = 1
  print x

  return 1

def main2(x):
  x['b'] = 2
  print x

p = Pool(2)
d = {1:{}, 2:{}}
r = p.map_async(main1, d.values())
print r.get()
print "main1", d

for x in d.values():
  main2(x)

print "main2", d
4

2 に答える 2

2

で変更可能な引数を変更していますmain1。しかし、それはプールを実行しているプロセスとは別のプロセスで発生します。彼らはデータを共有しません。

map_async実行されると、pythonは各反復からワーカー プロセスにデータをコピーします。ワーカー プロセスは関数を実行し、戻り値を収集して、それを実行中のプロセスに渡しますmap_async。変更された引数は返されません。

于 2012-09-11T22:54:18.193 に答える
1

r = p.map_async(main1, d.values())これを行います:

1)評価d.values()- それは[{}, {}]
2)main1(item)プールからのワーカーのそのリストの各項目に対して実行する
3)それらの呼び出しからの結果をリストに集める - [1, 1]- それがmain1返されるものだからです
4)そのリストをに割り当てますr

したがって、組み込み関数とまったく同じことを行いますmap()が、並列化された方法で行われます。

これは、 dictが渡された へのd参照ではないため、 、したがって.dmap_asyncmain1

また、参照をd- に渡しても、@Roland Smith で説明されている理由により機能しません。

ポイントは、そもそも辞書を変更してはならないということです。関数が引数を変更できるとしても、従来のプログラミングではあまり良いスタイルではありません。並列プログラミングでは、関数型プログラミング スタイルに従うことが絶対に重要です。これは、このコンテキストでは次のことを意味します。

関数は入力に対して計算を行い、さらに処理される結果を返す必要があります。

関数mapreduceは関数型プログラミングでは非常に一般的であり、それらを組み合わせることで、分散コンピューティングに非常に適したパターンを形成します。MapReduceに関するウィキペディアの記事から:

「マップ」ステップ: マスター ノードは入力を受け取り、それをより小さなサブ問題に分割し、それらをワーカー ノードに配布します。ワーカーノードはこれを順番に繰り返すことができ、マルチレベルのツリー構造につながります。ワーカー ノードは小さな問題を処理し、回答をマスター ノードに返します。

「縮小」ステップ: 次に、マスター ノードはすべての下位問題に対する回答を収集し、それらを何らかの方法で組み合わせて出力 (最初に解決しようとしていた問題に対する回答) を形成します。

したがって、プログラムを効果的に並列化するには、これらの関数の観点から問題を考えることが役立ちます。

非常に具体的な例については、記事The Trouble With Multicore in IEEE Spectrum を参照してください。map/reduce で簡単に実装できるPI の計算を並列化する方法について説明します。

于 2012-09-11T23:16:44.613 に答える