自从阅读本文后,我一直在使用multiprocessing,发现更新mp.Array 中的数据并不太难——让我感到惊讶的是,当使用循环迭代@987654323 时访问不是原子的@。下面的 sn-p 使用 mp.Process 设置了一个简单的 master-worker 集(使用 Pool 会更好,但这对我来说更快)其中 mp.Array 用于同步 master 经常更改的数据(尽可能快)
from multiprocessing import Process, RLock, Array
from time import sleep
def worker(n, array, arrayLock):
while True:
arrayLock.acquire()
print("Worker: %i -> %s" % (n, ",".join(str(i) for i in array)))
arrayLock.release()
sleep(n + 1)
if __name__ == '__main__':
arrayLock = RLock()
array = Array('i', range(10), lock=arrayLock)
pd = {}
for i in range(3):
pd[i] = Process(target=worker, args=(i, array, arrayLock))
pd[i].start()
try:
while True:
arrayLock.acquire()
for i in range(len(array)):
array[i] = -array[i]
arrayLock.release()
except KeyboardInterrupt:
pass
for p in pd.values():
p.terminate()
导致以下输出
~> python mp_shared.py
Worker: 0 -> 0,1,2,3,4,5,6,7,8,9
Worker: 1 -> 0,-1,-2,-3,-4,-5,-6,-7,-8,-9
Worker: 2 -> 0,1,2,3,4,5,6,7,8,9
Worker: 0 -> 0,-1,-2,-3,-4,-5,-6,-7,-8,-9
Worker: 1 -> 0,-1,-2,-3,-4,-5,-6,-7,-8,-9
Worker: 0 -> 0,1,2,3,4,5,6,7,8,9
跨进程更新数据只需更改Array 中的值即可。我遇到了一个问题,结果看起来像这样(注意数据的交替符号)
Worker: 0 -> 0,-1,2,-3,4,-5,6,-7,8,-9
Worker: 1 -> 0,-1,2,-3,4,-5,6,-7,8,-9
Worker: 2 -> 0,-1,2,-3,4,-5,6,-7,8,-9
这是因为当我读取或写入数组时,为Array 自动创建的Lock 不会同步整个循环的访问!主进程将进出Array,在工作人员获取锁之间进行更改。
为避免这种情况,我刚刚创建了自己的RLock(需要成为RLock,因为触摸Array 会使其获得,如果您已经获得Lock,则会阻止)用于@ 987654338@。我将RLock 传递给所有工作人员,以便他们每个人都可以进行原子操作(在您的情况下,我确信读写是原子的很重要,以防止梯度计算中的错误)。
编辑:
另一种选择似乎是mmap,但我无法评论它的使用以及此处是否可以按需要进行更改。