如何使用Python multiprocessing实现2D共享数组的访问与修改
问题原因
- 序列化机制导致共享内存关联丢失:你在主进程中通过
mp.Array创建共享内存后,基于该内存构建的numpy数组u在作为参数传入子进程时,会经过pickle序列化/反序列化流程。反序列化后的数组在子进程地址空间中是独立的副本,和原共享内存没有关联,子进程的所有修改都不会同步到主进程的共享内存中,所以最终主进程打印的数组还是初始的全零值。 - 存在竞态条件隐患:即使解决了共享内存关联问题,多个进程同时对同一个内存位置执行读写操作时,会出现执行顺序不可控的竞态问题,最终计算结果也会不符合预期。
修复后可运行代码
import multiprocessing as mp import numpy as np import ctypes as c n = 2 m = 3 def addData(shared_arr, lock, process_number): # 子进程内重新基于共享内存构建numpy数组 arr = np.frombuffer(shared_arr.get_obj(), c.c_int) array = arr.reshape((n, m)) i=0 # 加锁保证写入操作原子性 with lock: for nn in range(n): for mm in range(m): array[nn][mm] += i i=i+1 print("Array after process " + str(process_number)) print(array) if __name__=='__main__': # 初始化共享内存和进程锁 mp_arr = mp.Array('i', n*m) lock = mp.Lock() # 主进程初始化数组 arr = np.frombuffer(mp_arr.get_obj(), c.c_int) u = arr.reshape((n, m)) print("Array at the inital state: ") print(u) # 传入共享内存对象和锁,而非直接传numpy数组 p1 = mp.Process(target=addData, args=(mp_arr, lock, 1)) p2 = mp.Process(target=addData, args=(mp_arr, lock, 2)) p1.start() p2.start() p1.join() p2.join() print("Array at the final state: ") print(u)
关键修改说明
- 子进程参数改为传递
mp.Array共享内存对象本身,而非预构建的numpy数组,子进程内部再完成从共享内存到numpy数组的转换,保证操作的是同一块内存空间。 - 新增
mp.Lock进程锁,所有对共享数组的修改操作都在锁的保护下执行,避免多进程并发写入的竞态问题。
运行上述代码后,最终输出的数组就是你期望的[[0 2 4],[6 8 10]]。
内容的提问来源于stack exchange,提问作者Paulo Rocha
相关产品推荐
相关产品推荐

