我看到的这段代码看起来像这样:
glbl_array = # a 3 Gb array
def my_func( args, def_param = glbl_array):
#do stuff on args and def_param
if __name__ == '__main__':
pool = Pool(processes=4)
pool.map(my_func, range(1000))
有没有办法确保(或鼓励)不同的进程没有获得glbl_array的副本但是共享它。如果没有办法停止复制,我将使用memmapped数组,但我的访问模式不是很规律,所以我希望memmapped数组更慢。以上似乎是第一个尝试的事情。这是在Linux上。我只是想从Stackoverflow获得一些建议,并且不想惹恼系统管理员。如果第二个参数是真正的不可变对象,如glbl_array.tostring()
。
答案 0 :(得分:99)
您可以非常轻松地使用multiprocessing
和Numpy的共享内存:
import multiprocessing
import ctypes
import numpy as np
shared_array_base = multiprocessing.Array(ctypes.c_double, 10*10)
shared_array = np.ctypeslib.as_array(shared_array_base.get_obj())
shared_array = shared_array.reshape(10, 10)
#-- edited 2015-05-01: the assert check below checks the wrong thing
# with recent versions of Numpy/multiprocessing. That no copy is made
# is indicated by the fact that the program prints the output shown below.
## No copy was made
##assert shared_array.base.base is shared_array_base.get_obj()
# Parallel processing
def my_func(i, def_param=shared_array):
shared_array[i,:] = i
if __name__ == '__main__':
pool = multiprocessing.Pool(processes=4)
pool.map(my_func, range(10))
print shared_array
打印
[[ 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
[ 2. 2. 2. 2. 2. 2. 2. 2. 2. 2.]
[ 3. 3. 3. 3. 3. 3. 3. 3. 3. 3.]
[ 4. 4. 4. 4. 4. 4. 4. 4. 4. 4.]
[ 5. 5. 5. 5. 5. 5. 5. 5. 5. 5.]
[ 6. 6. 6. 6. 6. 6. 6. 6. 6. 6.]
[ 7. 7. 7. 7. 7. 7. 7. 7. 7. 7.]
[ 8. 8. 8. 8. 8. 8. 8. 8. 8. 8.]
[ 9. 9. 9. 9. 9. 9. 9. 9. 9. 9.]]
但是,Linux在fork()
上具有写时复制语义,因此即使不使用multiprocessing.Array
,除非写入数据,否则不会复制数据。
答案 1 :(得分:4)
以下代码适用于Win7和Mac(可能在Linux上,但未经过测试)。
import multiprocessing
import ctypes
import numpy as np
#-- edited 2015-05-01: the assert check below checks the wrong thing
# with recent versions of Numpy/multiprocessing. That no copy is made
# is indicated by the fact that the program prints the output shown below.
## No copy was made
##assert shared_array.base.base is shared_array_base.get_obj()
shared_array = None
def init(shared_array_base):
global shared_array
shared_array = np.ctypeslib.as_array(shared_array_base.get_obj())
shared_array = shared_array.reshape(10, 10)
# Parallel processing
def my_func(i):
shared_array[i, :] = i
if __name__ == '__main__':
shared_array_base = multiprocessing.Array(ctypes.c_double, 10*10)
pool = multiprocessing.Pool(processes=4, initializer=init, initargs=(shared_array_base,))
pool.map(my_func, range(10))
shared_array = np.ctypeslib.as_array(shared_array_base.get_obj())
shared_array = shared_array.reshape(10, 10)
print shared_array
答案 2 :(得分:2)
对于那些使用Windows而不支持fork()
的人(除非使用CygWin),pv的答案不起作用。全球不适用于子进程。
相反,您必须在Pool
/ Process
的初始值设定项中传递共享内存:
#! /usr/bin/python
import time
from multiprocessing import Process, Queue, Array
def f(q,a):
m = q.get()
print m
print a[0], a[1], a[2]
m = q.get()
print m
print a[0], a[1], a[2]
if __name__ == '__main__':
a = Array('B', (1, 2, 3), lock=False)
q = Queue()
p = Process(target=f, args=(q,a))
p.start()
q.put([1, 2, 3])
time.sleep(1)
a[0:3] = (4, 5, 6)
q.put([4, 5, 6])
p.join()
(它并不是numpy而且它不是很好的代码,但它说明了这一点; - )
答案 3 :(得分:0)
如果您正在寻找一种在Windows上高效运行的选项,并且适用于不规则访问模式,分支以及您可能需要基于共享内存矩阵和流程的组合分析不同矩阵的其他方案 - 本地数据,ParallelRegression包中的mathDict工具包旨在处理这种情况。