为 Read/Write 速度优化 HDF5 数据集
Optimising HDF5 dataset for Read/Write speed
我目前正在 运行 进行一项实验,在该实验中我在空间上扫描目标并在每个离散像素处抓取示波器轨迹。通常我的走线长度是 200Kpts。在扫描整个目标后,我 assemble 这些时域信号在空间上和本质上播放扫描内容的电影。我的扫描区域大小为 330x220 像素,因此整个数据集比我必须使用的计算机上的 RAM 大。
首先,我只是将每个示波器迹线保存为一个 numpy 数组,然后在我完成扫描后 downsampling/filtering 等,然后以 运行 无法实现的方式将电影拼凑在一起内存问题。但是,我现在无法进行缩减采样,因为会出现混叠,因此需要访问原始数据。
我已经开始考虑使用 H5py 将大型 3d 数据块存储在 HDF5 数据集中。我的主要问题是我的块大小分配。我的传入数据与我想在其中读出的平面正交。我写入数据的主要选项(据我所知)是:
#Fast write Slow read
with h5py.File("test_h5py.hdf5","a") as f:
dset = f.create_dataset("uncompchunk",(height,width,dataLen),chunks = (1,1,dataLen), dtype = 'f')
for i in range(height):
for j in range(width):
dset[i,j,:] = np.random.random(200000)
或
#Slow write Fast read
with h5py.File("test_h5py.hdf5","a") as f:
dset = f.create_dataset("uncompchunk",(height,width,dataLen),chunks = (height,width,1), dtype = 'f')
for i in range(height):
for j in range(width):
dset[i,j,:] = np.random.random(200000)
有什么方法可以优化这两种情况,使两者都不会比 运行 效率低下吗?
如果您想通过分块优化 I/O 性能,您应该阅读来自 unidata 的这两篇文章:
如果您只想要原始 I/O 性能,请考虑@titusjan 建议
您的代码存在一些性能缺陷。
- 您在该行中使用了某种奇特的索引(在读取/写入 HDF5 数据集时不要更改数组暗淡的数量。
如果您不读取或写入整个块,请设置适当的块缓存大小。
减少对 HDF5-Api 的读取或写入调用量。
- 选择合适的块大小(块只能 read/written 完整,因此如果您只需要块的一部分,其余部分应保留在缓存中)
以下示例使用 HDF5-API 的缓存。要设置适当的缓存大小,我将使用 h5py_cache。
https://pypi.python.org/pypi/h5py-cache/1.0.1
如果您自己进行缓存,您可以进一步提高性能。 (读写整个块)
写作
# minimal chache size for reasonable performance would be 20*20*dataLen*4= 320 MB, lets take a bit more
with h5py_cache.File(h5pyfile, 'r+',chunk_cache_mem_size=500*1024**2) as f:
dset = f.create_dataset("uncompchunk",(height,width,dataLen),chunks = (20,20,20), dtype = 'f')
for i in range(height):
for j in range(width):
# avoid fancy slicing
dset[i:i+1,j:j+1,:] = expand_dims(expand_dims(np.random.random(200000),axis=0),axis=0)
阅读
# minimal chache size for reasonable performance would be height*width*500*4= 145 MB, lets take a bit more
with h5py_cache.File(h5pyfile, 'r+',chunk_cache_mem_size=200*1024**2) as f:
dset=f["uncompchunk"]
for i in xrange(0,dataLen):
Image=np.squeeze(dset[:,:,i:i+1])
我目前正在 运行 进行一项实验,在该实验中我在空间上扫描目标并在每个离散像素处抓取示波器轨迹。通常我的走线长度是 200Kpts。在扫描整个目标后,我 assemble 这些时域信号在空间上和本质上播放扫描内容的电影。我的扫描区域大小为 330x220 像素,因此整个数据集比我必须使用的计算机上的 RAM 大。
首先,我只是将每个示波器迹线保存为一个 numpy 数组,然后在我完成扫描后 downsampling/filtering 等,然后以 运行 无法实现的方式将电影拼凑在一起内存问题。但是,我现在无法进行缩减采样,因为会出现混叠,因此需要访问原始数据。
我已经开始考虑使用 H5py 将大型 3d 数据块存储在 HDF5 数据集中。我的主要问题是我的块大小分配。我的传入数据与我想在其中读出的平面正交。我写入数据的主要选项(据我所知)是:
#Fast write Slow read
with h5py.File("test_h5py.hdf5","a") as f:
dset = f.create_dataset("uncompchunk",(height,width,dataLen),chunks = (1,1,dataLen), dtype = 'f')
for i in range(height):
for j in range(width):
dset[i,j,:] = np.random.random(200000)
或
#Slow write Fast read
with h5py.File("test_h5py.hdf5","a") as f:
dset = f.create_dataset("uncompchunk",(height,width,dataLen),chunks = (height,width,1), dtype = 'f')
for i in range(height):
for j in range(width):
dset[i,j,:] = np.random.random(200000)
有什么方法可以优化这两种情况,使两者都不会比 运行 效率低下吗?
如果您想通过分块优化 I/O 性能,您应该阅读来自 unidata 的这两篇文章:
如果您只想要原始 I/O 性能,请考虑@titusjan 建议
您的代码存在一些性能缺陷。
- 您在该行中使用了某种奇特的索引(在读取/写入 HDF5 数据集时不要更改数组暗淡的数量。
如果您不读取或写入整个块,请设置适当的块缓存大小。
减少对 HDF5-Api 的读取或写入调用量。
- 选择合适的块大小(块只能 read/written 完整,因此如果您只需要块的一部分,其余部分应保留在缓存中)
以下示例使用 HDF5-API 的缓存。要设置适当的缓存大小,我将使用 h5py_cache。 https://pypi.python.org/pypi/h5py-cache/1.0.1
如果您自己进行缓存,您可以进一步提高性能。 (读写整个块)
写作
# minimal chache size for reasonable performance would be 20*20*dataLen*4= 320 MB, lets take a bit more
with h5py_cache.File(h5pyfile, 'r+',chunk_cache_mem_size=500*1024**2) as f:
dset = f.create_dataset("uncompchunk",(height,width,dataLen),chunks = (20,20,20), dtype = 'f')
for i in range(height):
for j in range(width):
# avoid fancy slicing
dset[i:i+1,j:j+1,:] = expand_dims(expand_dims(np.random.random(200000),axis=0),axis=0)
阅读
# minimal chache size for reasonable performance would be height*width*500*4= 145 MB, lets take a bit more
with h5py_cache.File(h5pyfile, 'r+',chunk_cache_mem_size=200*1024**2) as f:
dset=f["uncompchunk"]
for i in xrange(0,dataLen):
Image=np.squeeze(dset[:,:,i:i+1])