来自numpy数组的RawArray?

时间:2014-10-10 15:05:16

标签: python arrays numpy multiprocessing

我想在多个进程之间共享一个numpy数组。这些进程只读取数据,所以我想避免复制。如果我可以从multiprocessing.sharedctypes.RawArray开始,然后使用numpy.frombuffer创建一个numpy数组,我知道该怎么做。但是,如果我最初得到一个numpy数组怎么办?有没有办法用numpy数组的数据初始化RawArray而不复制数据?或者是否有另一种方法可以跨进程共享数据而无需复制它?

4 个答案:

答案 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)

据我所知,在将内存分配给特定进程后,不可能将其声明为共享。可以在herehere (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]