我想在多个进程之间共享一个numpy数组。这些进程只读取数据,所以我想避免复制。如果我可以从multiprocessing.sharedctypes.RawArray
开始,然后使用numpy.frombuffer
创建一个numpy数组,我知道该怎么做。但是,如果我最初得到一个numpy数组怎么办?有没有办法用numpy数组的数据初始化RawArray而不复制数据?或者是否有另一种方法可以跨进程共享数据而无需复制它?
答案 0 :(得分:1)
我也有一些你的要求:a)给定一个大的numpy数组,b)需要在一堆进程中共享它c)只读等等。为此,我一直在使用的东西沿着:
mynparray = #initialize a large array from a file
shrarr_base_ptr = RawArray(ctypes.c_double, len*rows*cols)
shrarr_ptr = np.frombuffer(shrarr_base_ptr)
shrarr_ptr = mynparray
在我的情况下,mynparray是3-D。至于实际的共享,我使用了以下样式,它到目前为止一直有效。
inq1 = Queue()
inq2 = Queue()
outq = Queue()
p1 = Process(target = myfunc1, args=(inq1, outq,))
p1.start()
inq1.put((shrarr_ptr, ))
p2 = Process(target = myfunc2, args=(inq2, outq,))
p2.start()
inq2.put((shrarr_ptr,))
inq1.close()
inq2.close()
inq1.join_thread()
inq2.join_thread()
....
答案 1 :(得分:1)
据我所知,在将内存分配给特定进程后,不可能将其声明为共享。可以在here和here (more suitable)中找到类似的讨论。
让我快速勾勒出您提到的解决方法(从RawArray
开始并获得numpy.ndarray
的引用)。
import numpy as np
from multiprocessing.sharedctypes import RawArray
# option 1
raw_arr = RawArray(ctypes.c_int, 12)
# option 2 (set is up, similar to some existing np.ndarray np_arr2)
raw_arr = RawArray(
np.ctypeslib.as_ctypes_type(np_arr2.dtype), len(np_arr2)
)
np_arr = np.frombuffer(raw_arr, dtype=np.dtype(raw_arr))
# np_arr: numpy array with shared memory, can be processed by multiprocessing
如果必须以numpy.ndarray
开始,则除了复制数据外别无选择
import numpy as np
from multiprocessing.sharedctypes import RawArray
np_arr = np.zeros(shape=(3, 4), dtype=np.ubyte)
# option 1
tmp = np.ctypeslib.as_ctypes(np_arr)
raw_arr = RawArray(tmp._type_, tmp)
# option 2
raw_arr = RawArray(np.ctypeslib.as_ctypes_type(np_arr.dtype), np_arr.flatten())
print(raw_arr[:])
答案 2 :(得分:0)
请注意,如果您打算使用numpy数组,则可以完全省略 │ (0, 0) │ (0, 1) │ (0, 2) ║ (0, 3) │
│ (1, 0) │ (1, 1) │ (1, 2) ║ (1, 3) │
│ (2, 0) │ (2, 1) │ (2, 2) ║ (2, 3) │
│ (3, 0) │ (3, 1) │ (3, 2) ║ (3, 3) │
并使用:
RawArray
这种方法的优点是它可以在from multiprocessing.heap import BufferWrapper
def shared_array(shape, dtype):
dt = np.dtype((dtype, shape))
wrapper = BufferWrapper(dt.itemsize)
mem = wrapper.create_memoryview()
# workaround for bpo-41673 to keep `wrapper` alive
ct = (ctypes.c_ubyte * dt.itemsize).from_buffer(mem)
ct._owner = wrapper
mem = memoryview(ct)
return np.asarray(mem).view(dt)
失败的情况下使用。
答案 3 :(得分:-1)
我不确定这是否会在内部复制数据,但您可以传递平面数组:
a = numpy.random.randint(1,10,(4,4))
>>> a
array([[5, 6, 7, 7],
[7, 9, 2, 8],
[3, 4, 6, 4],
[3, 1, 2, 2]])
b = RawArray(ctypes.c_long, a.flat)
>>> b[:]
[5, 6, 7, 7, 7, 9, 2, 8, 3, 4, 6, 4, 3, 1, 2, 2]