1

私が見ている問題を説明するために、次のコードを書きました。Process.Manager.list()リストを追跡し、そのリストのランダムなインデックスをインクリメントするためにa を使用しようとしています。

100 個のプロセスが生成されるたびに、各プロセスはリストのランダム インデックスを 1 ずつ増やします。したがって、結果のリストの SUM は毎回同じであると予想されますよね? 203 から 205 の間の何かを取得します。

from multiprocessing import Process, Manager
import random

class MyProc(Process):
    def __init__(self, A):
        Process.__init__(self)
        self.A = A

    def run(self):
        i = random.randint(0, len(self.A)-1)
        self.A[i] = self.A[i] + 1

if __name__ == '__main__':
    procs = []
    M = Manager()
    a = M.list(range(15))
    print('A: {0}'.format(a))
    print('sum(A) = {0}'.format(sum(a)))

    for i in range(100):
        procs.append(MyProc(a))

    map(lambda x: x.start(), procs)
    map(lambda x: x.join(), procs)
    print('A: {0}'.format(a))
    print('sum(A) = {0}'.format(sum(a)))
4

2 に答える 2

3

ミリムース指摘しているように、ここでの問題はで発生する競合状態self.A[i] = self.A[i] + 1です。self.A[i] + 1計算されるまでself.A[i]に、別のプロセスによってすでに変更されている可能性があります。

問題の考えられる解決策は、インデックスを親に戻し、親が加算を実行することです。

from multiprocessing import Process, Manager
import random

class MyProc(Process):
    def __init__(self, B, length):
        Process.__init__(self)
        self.B = B
        self.length = length

    def run(self):
        i = random.randint(0, self.length-1)
        self.B.append(i)

if __name__ == '__main__':
    procs = []
    M = Manager()
    a = range(15)
    b = M.list()
    print('A: {0}'.format(a))
    print('sum(A) = {0}'.format(sum(a)))

    for i in range(100):
        procs.append(MyProc(b, len(a)))

    map(lambda x: x.start(), procs)
    map(lambda x: x.join(), procs)

    for i in b:
        a[i] = a[i] + 1

    print('A: {0}'.format(a))
    print('sum(A) = {0}'.format(sum(a)))

配列への要素の追加は1つの操作のみであるため、競合状態が回避されます。

于 2012-10-31T22:59:16.583 に答える
1

上記のコメントから回答が得られました。次の行が原因で競合状態が発生しています。

self.A[i] = self.A[i] + 1

実際には、a__getitem__とaの2つの操作です。__setitem__

于 2012-10-31T22:58:44.517 に答える