在多个进程之间共享numpy数组而不使用继承

6
我希望能够在多个进程之间共享numpy数组。这里有一些可行的解决方案(链接)。但是它们都通过继承将数组传递给子进程,这对我来说不起作用,因为我必须先启动几个工作进程,而且我不知道以后会处理多少个数组。是否有任何方法可以在进程启动后创建这些数组,并通过队列将这些数组传递给进程?
顺便说一下,由于某种原因,我无法使用multiprocessing.Manager

这里的“继承”是什么意思? - Eric
@Eric 当您创建一个进程时,内部会执行 fork 系统调用,并且子进程会继承父进程的所有程序状态,包括共享内存句柄。避免通过继承传递的示例在此处:https://dev59.com/OWkw5IYBdhLWcg3waZ74 - shaoyl85
3
使用pyzmq交换数组非常快速和灵活: https://github.com/zeromq/pyzmq/blob/master/examples/serialization/serialsocket.py - Niemerds
@Niemerds 谢谢!如果我使用multiprocessing.Queue发送数组,它会调用pickle dumps,然后通过管道发送转储的字符串。使用pyzmq是否可以加速这些步骤中的任何一个? - shaoyl85
当然。pickle函数将数组数据转换为(un-)pickle操作使用的二进制格式,而在接收方,它又进行了相反的转换。而pyzmq方法则使用缓冲区接口未经修改地发送/接收numpy数据。因此,避免了在两端进行不必要的数据复制或转换。 - Niemerds
显示剩余2条评论
2个回答

3
你应该使用共享内存,它可以精确地解决你的使用情况。这样可以保持内存读写速度,并且所有进程都可以在共享内存中读写数组,而不会产生任何序列化或传输成本。

以下是官方 Python 文档的示例:

>>> # In the first Python interactive shell
>>> import numpy as np
>>> a = np.array([1, 1, 2, 3, 5, 8])  # Start with an existing NumPy array
>>> from multiprocessing import shared_memory
>>> shm = shared_memory.SharedMemory(create=True, size=a.nbytes)
>>> # Now create a NumPy array backed by shared memory
>>> b = np.ndarray(a.shape, dtype=a.dtype, buffer=shm.buf)
>>> b[:] = a[:]  # Copy the original data into shared memory
>>> b
array([1, 1, 2, 3, 5, 8])
>>> type(b)
<class 'numpy.ndarray'>
>>> type(a)
<class 'numpy.ndarray'>
>>> shm.name  # We did not specify a name so one was chosen for us
'psm_21467_46075'

>>> # In either the same shell or a new Python shell on the same machine
>>> import numpy as np
>>> from multiprocessing import shared_memory
>>> # Attach to the existing shared memory block
>>> existing_shm = shared_memory.SharedMemory(name='psm_21467_46075')
>>> # Note that a.shape is (6,) and a.dtype is np.int64 in this example
>>> c = np.ndarray((6,), dtype=np.int64, buffer=existing_shm.buf)
>>> c
array([1, 1, 2, 3, 5, 8])
>>> c[-1] = 888
>>> c
array([  1,   1,   2,   3,   5, 888])

>>> # Back in the first Python interactive shell, b reflects this change
>>> b
array([  1,   1,   2,   3,   5, 888])

>>> # Clean up from within the second Python shell
>>> del c  # Unnecessary; merely emphasizing the array is no longer used
>>> existing_shm.close()

>>> # Clean up from within the first Python shell
>>> del b  # Unnecessary; merely emphasizing the array is no longer used
>>> shm.close()
>>> shm.unlink()  # Free and release the shared memory block at the very end

对于像你这样的真实用例,你需要使用Pipe或其他多进程通信机制传递名称shm.name。请注意,只需在进程之间交换此小字符串即可;实际数据保留在共享内存空间中。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接