[英]How to share memory from an HDF5 dataset with a NumPy ndarray
我正在編寫一個來自傳感器的流數據應用程序,然后以各種方式處理數據。 這些處理組件包括可視化數據,一些數字運算(線性代數),以及以HDF5格式將數據寫入磁盤。 理想情況下,這些組件中的每一個都是它自己的模塊,所有模塊都在同一個Python進程中運行,因此IPC不是問題。 這引出了如何有效存儲流數據的問題。
數據集非常大(~5Gb),因此我希望通過在需要訪問的組件之間共享數據來最小化內存中數據的副本數量。 如果所有組件都直接使用ndarray
,那么這應該是直截了當的:給其中一個進程提供數據,然后使用ndarray.view()
給其他人一個副本。
然而,該組件將數據寫入到磁盤存儲在HDF5數據Dataset
。 這些可以通過ndarray
方式與ndarray
進行互操作,但似乎創建一個view()
不像ndarrary
那樣工作。
觀察與ndarray
s:
>>> source = np.zeros((10,))
>>> view = source.view()
>>> source[0] = 1
>>> view[0] == 1
True
>>> view.base is source
True
但是,這不適用於HDF5 Dataset
:
>>> import h5py
>>> file = h5py.File('source.h5', 'a')
>>> source_dset = file.create_dataset('source', (10,), dtype=np.float64)
>>> view_dset = source_dset.value.view()
>>> source_dset[0] = 1
>>> view_dset[0] == 1
False
>>> view_dset.base is source_dset.value
False
它也不能僅僅分配Dataset.value
本身,而不是它的view
。
>>> view_dset = source_dset.value
>>> source_dset[0] = 2
>>> view_dset[0] == 2
False
>>> view_dset.base is source_dset.value
False
所以我的問題是: 有沒有辦法讓一個ndarray
共享內存與HDF5 Dataset
,就像兩個ndarray
可以共享內存?
我的猜測是,這不太可行,可能是因為HDF5如何將數組存儲在內存中。 但這對我來說有點混亂,尤其是type(source_dset.value) == numpy.ndarray
和Dataset.value.view()
的OWNDATA
標志實際上是False
。 誰擁有該view
所解釋的記憶?
版本詳細信息:Python 3,NumPy版本1.9.1,h5py版本2.3.1,HDF5版本1.8.13,Linux。
其他細節:HDF5文件被分塊。
編輯 :
在更多地討論之后,似乎一種可能的解決方案是給其他組件提供對HDF5 Dataset
本身的引用。 這似乎不會復制任何內存(至少不是根據top
),並且源Dataset
集中的更改將反映在視圖中。
>>> import h5py
>>> file = h5py.File('source.h5', 'a')
>>> source = file.create_dataset('source', (10,), dtype=np.float64)
>>> class Container():
... def __init__(self, source_dset):
... self.dset = source_dset
...
>>> container = Containter(source)
>>> source[0] = 1
>>> container.dset[0] == 1
True
我對這個解決方案感到相當滿意(只要節省內存),但我仍然很好奇為什么上面的view
方法不起作用。
簡短的回答是你不能在numpy
數組和h5py
數據集之間共享內存。 雖然它們具有類似的API(至少在索引方面),但它們沒有兼容的內存布局。 實際上,除了緩存之外,數據集甚至不在內存中 - 它位於文件中。
首先,我不明白為什么你需要使用帶有numpy
數組的source.view()
。 是的,當從數組中選擇或重塑數組時, numpy
嘗試返回view
而不是副本。 但是.view
大多數(所有?)示例都涉及某種轉換,例如dtype
。 你能用.view()
指向代碼或文檔示例嗎?
我對h5py
沒有多少經驗,但是它的文檔討論了它為h5
文件對象提供了一個類似ndarray的薄包裝。 您的DataSet
不是ndarray
。 例如,它缺少許多ndarray
方法,包括view
。
但索引DataSet
返回一個ndarray
,例如view_dset[:]
。 .value
。 它的文檔的第一部分(通過IPython
view_dset.value??
):
Type: property
String form: <property object at 0xb4ee37d4>
Docstring: Alias for dataset[()]
...
請注意,將新值分配給DataSet時,必須直接索引source_dset
。 索引值不起作用 - 除了修改數組。 它不會更改文件對象。
從數組創建數據集不會將它們更緊密地鏈接起來:
x = np.arange(10)
xdset = file.create_dataset('x', data=x)
x1 = xdset[:]
x
, xdset
和x1
都是獨立的 - 改變一個不會改變其他的。
關於時代,比較
timeit np.sum(x) # 11.7 µs
timeit np.sum(xdset) # 203 µs
timeit xdset.value # 173 µs
timeit np.sum(x1) # same as for x
數組的sum
比數據集快得多。 大多數額外時間都涉及從數據集創建數組。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.