为何Python多进程无法修改二维数组行?如何解决?
问题原因
你用mp.Manager().list()创建的外层列表是进程共享对象,但里面的子列表a[0]、a[1]是普通Python列表,不属于进程共享范畴。当你把这些子列表传给子进程时,它们会被pickle序列化后复制到子进程的独立内存空间——子进程修改的只是自己手里的副本,完全碰不到主进程里的原列表元素,所以主进程最后打印的还是初始值。
解决方案1:嵌套使用Manager共享列表
把每个子列表也改成mp.Manager().list()类型,让所有层级的列表都是进程共享对象,子进程的修改会同步回主进程:
import multiprocessing as mp def incr(a): for i in range(len(a)): a[i] += 1 if __name__ == "__main__": manager = mp.Manager() # 外层和内层都用Manager创建共享列表 a = manager.list([ manager.list([0, 1, 2]), manager.list([3, 4, 5]) ]) with mp.Pool(2) as pool: pool.map(incr, [a[0], a[1]]) print(a) # 输出: [[1, 2, 3], [4, 5, 6]]
解决方案2:子进程返回结果,主进程更新
不依赖共享对象,让子进程处理完子列表后返回新结果,主进程再替换原数组的对应行:
import multiprocessing as mp def incr(a): # 返回修改后的新列表 return [x + 1 for x in a] if __name__ == "__main__": a = [[0, 1, 2], [3, 4, 5]] with mp.Pool(2) as pool: # 接收子进程返回的所有修改后行 updated_rows = pool.map(incr, a) a = updated_rows print(a) # 输出: [[1, 2, 3], [4, 5, 6]]
这种方式逻辑简单,避免了共享对象的同步开销,适合大多数场景。
解决方案3:使用共享内存数组(适合数值型数据)
如果你的数组是纯数值类型(整数、浮点数等),可以用mp.Array创建基于共享内存的数组,配合numpy操作更高效:
import multiprocessing as mp import numpy as np def incr(arr, row_idx): # 将共享内存数组转为numpy数组切片 np_arr = np.frombuffer(arr.get_obj(), dtype=np.int32).reshape(2, 3) np_arr[row_idx] += 1 if __name__ == "__main__": # 创建共享内存数组,指定类型为int32,长度6(对应2行3列) shared_arr = mp.Array('i', [0,1,2,3,4,5]) # 转为numpy数组方便操作 a = np.frombuffer(shared_arr.get_obj(), dtype=np.int32).reshape(2,3) with mp.Pool(2) as pool: # 给每个进程传共享数组和要处理的行索引 pool.starmap(incr, [(shared_arr, 0), (shared_arr, 1)]) print(a) # 输出: [[1 2 3] # [4 5 6]]
这种方式性能最优,直接操作共享内存,没有序列化复制的开销,但仅适合数值类型,需要处理数组形状转换。
内容的提问来源于stack exchange,提问作者Paul Jurczak
相关产品推荐
相关产品推荐

