[英]Updating shared read-only data with Python multiprocessing
我正在尝试使用Python的多处理库来试验分布式神经网络。 目前,我已经进行了设置,以便服务器进程创建神经网络并分块输入以进行小批量梯度下降,并将批处理放入共享队列中,由客户端进程处理,并将结果放入单独的共享队列。
到目前为止,一切工作正常,只是为了处理批次并产生渐变,子进程需要网络权重的副本,我已使用多处理数组共享了网络权重。 客户端进程仅需要权重的只读副本,但是服务器进程在每个训练时期之后都会更新本地副本。
我的问题是如何更新共享内存以反映更改的权重,以便在下一个时期,客户端进程具有用于计算梯度的正确值。
自从阅读mp.Array
以来,我一直在mp.Array
multiprocessing
工作,发现更新mp.Array
数据并不是太难-使我感到有点mp.Array
的事实是,使用循环迭代Array
时访问不是原子的。 下面的代码片段使用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
读写时,为Array
自动创建的Lock
不会同步整个循环的访问! 主进程将在Array
拉入和拉出,从而在工作人员获取锁之间进行更改。
为了避免这种情况,我刚刚创建了自己的RLock
(需要一个RLock
因为触摸Array
会使其获取,如果您已经获得Lock
,它将阻塞,如果与Array
一起使用)。 我将RLock
传递给所有工人,这样他们每个人都可以进行原子操作(在您的情况下,我相信读写是原子的,以防止梯度计算中的错误很重要)。
编辑:
另一个替代方案似乎是mmap
但我无法评论其用途以及此处是否mmap
更改。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.