[英]Sharing array of objects with Python multiprocessing
For this question, I refer to the example in Python docs discussing the "use of the SharedMemory
class with NumPy
arrays, accessing the same numpy.ndarray
from two distinct Python shells".
我想實現的一個主要更改是操作 class 對象數組,而不是 integer 值,如下所示。
import numpy as np
from multiprocessing import shared_memory
# a simplistic class example
class A():
def __init__(self, x):
self.x = x
# numpy array of class objects
a = np.array([A(1), A(2), A(3)])
# create a shared memory instance
shm = shared_memory.SharedMemory(create=True, size=a.nbytes, name='psm_test0')
# numpy array backed by shared memory
b = np.ndarray(a.shape, dtype=a.dtype, buffer=shm.buf)
# copy the original data into shared memory
b[:] = a[:]
print(b)
# array([<__main__.Foo object at 0x7fac56cd1190>,
# <__main__.Foo object at 0x7fac56cd1970>,
# <__main__.Foo object at 0x7fac56cd19a0>], dtype=object)
現在,在不同的 shell 中,我們附加到共享的 memory 空間並嘗試操作數組的內容。
import numpy as np
from multiprocessing import shared_memory
# attach to the existing shared space
existing_shm = shared_memory.SharedMemory(name='psm_test0')
c = np.ndarray((3,), dtype=object, buffer=existing_shm.buf)
甚至在我們能夠操作c
,打印它就會導致分段錯誤。 事實上,我不能指望觀察到尚未寫入模塊的行為,所以我的問題是如何處理共享對象數組?
我目前正在挑選列表,但受保護的讀/寫會增加相當多的開銷。 我也嘗試過使用Namespace
,這很慢,因為不允許索引寫入。 另一個想法可能是在 ShareableList 中使用ShareableList
Ctypes 結構,但我不知道從哪里開始。
此外還有一個設計方面: shared_memory
中似乎有一個開放的錯誤可能會影響我的實現,其中我有幾個進程在處理數組的不同元素。
是否有一種更可擴展的方式在多個進程之間共享大量對象列表,以便在任何給定時間所有正在運行的進程都與列表中的唯一對象/元素交互?
更新:在這一點上,我也將接受部分答案,討論是否可以通過 Python 來實現。
所以,我做了一些研究( Shared Memory Objects in Multiprocessing )並提出了一些想法:
序列化對象,然后將它們作為字節字符串保存到 numpy 數組中。 這里有問題的是
需要將數據類型從 'psm_test0' 的創建者傳遞給 ' 'psm_test0'
'psm_test0'
的任何消費者。 這可以通過另一個共享的 memory 來完成。
pickle
和unpickle
本質上類似於deepcopy
,即它實際上復制了底層數據。
“主”進程的代碼如下:
import pickle
from multiprocessing import shared_memory
import numpy as np
# a simplistic class example
class A():
def __init__(self, x):
self.x = x
def pickle(self):
return pickle.dumps(self)
@classmethod
def unpickle(self, bts):
return pickle.loads(bts)
if __name__ == '__main__':
# Test pickling procedure
a = A(1)
print(A.unpickle(a.pickle()).x)
# >>> 1
# numpy array of byte strings
a_arr = np.array([A(1).pickle(), A(2).pickle(), A('This is a really long test string which should exceed 42 bytes').pickle()])
# create a shared memory instance
shm = shared_memory.SharedMemory(
create=True,
size=a_arr.nbytes,
name='psm_test0'
)
# numpy array backed by shared memory
b_arr = np.ndarray(a_arr.shape, dtype=a_arr.dtype, buffer=shm.buf)
# copy the original data into shared memory
b_arr[:] = a_arr[:]
print(b_arr.dtype)
# 'S105'
並且對於消費者
import numpy as np
from multiprocessing import shared_memory
from test import A
# attach to the existing shared space
existing_shm = shared_memory.SharedMemory(name='psm_test0')
c = np.ndarray((3,), dtype='S105', buffer=existing_shm.buf)
# Test data transfer
arr = [a.x for a in list(map(A.unpickle, c))]
print(arr)
# [1, 2, ...]
我想說你有幾種前進的方法:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.