查找正确的块缓存大小

一开始我不想讨论一些一般的事情。

重要的是要知道,每个单独的块只能作为一个整体来读或写。h5py的标准块缓存大小可以避免过多的磁盘I/o,每个默认值只有1 MB,在许多情况下应该增加,这将在后面讨论。在

例如:我们有一个形状为(63903810000)、float32(25,5gb未压缩)的数据集

我们不需要按dset[:,i]=arr编写数据列,而按行读取arr=dset[i,:]

我们为这类工作选择了一个完全错误的块形状,即(110000)

在这种情况下,读取速度不会太差(尽管块大小有点小),因为我们只读取正在使用的数据。但是当我们在这个数据集上写的时候会发生什么呢?如果我们访问一个列,则写入每个块的一个浮点数。这意味着我们实际上是在每次迭代中编写整个数据集(25,5gb),并每隔一次读取整个数据集。这是因为如果你修改了一个区块,如果它没有被缓存,你必须先读取它(这里的区块缓存大小小于25.5gb)。在

那么我们能在这方面改进什么呢?

在这种情况下,我们必须在写/读速度和块缓存使用的内存之间进行折衷。在

一个假设,该假设将提供适当的/读和写速度:我们选择块大小为(1001000)

如果我们不想迭代第一个维度,我们至少需要(1000*639038*4->2,55GB)缓存,以避免如上所述的额外IO开销和(100*10000*4->0,4 MB)。在

所以在这个例子中,我们应该提供至少2,6gb的块数据缓存。使用h5py缓存https://pypi.python.org/pypi/h5py-cache/1.0可以轻松实现这一点

结论

没有一般正确的块大小或形状,这在很大程度上取决于使用哪一个任务。在选择块大小或形状时,一定要考虑块缓存。在随机读/写方面,RAM比最快的SSD快几个数量级。在

关于您的问题

我只需读取随机行,不正确的块缓存大小才是真正的问题。在

将以下代码的性能与您的版本进行比较:import h5py as h5

import time
import numpy as np
import h5py_cache as h5c
def ReadingAndWriting():
File_Name_HDF5='Test.h5'
shape = (639038, 10000)
chunk_shape=(100, 1000)
Array=np.array(np.random.rand(shape[0]),np.float32)
#We are using 4GB of chunk_cache_mem here
f = h5c.File(File_Name_HDF5, 'w',chunk_cache_mem_size=1024**2*4000)
d = f.create_dataset('Test', shape ,dtype='f',chunks=chunk_shape,compression="lzf")
#Writing columns
t1=time.time()
for i in xrange(0,shape[1]):
d[:,i:i+1]=np.expand_dims(Array, 1)
f.close()
print(time.time()-t1)
# Reading random rows
# If we read one row there are actually 100 read, but if we access a row
# which is already in cache we would see a huge speed up.
f = h5c.File(File_Name_HDF5,'r',chunk_cache_mem_size=1024**2*4000)
d = f["Test"]
for j in xrange(0,639):
t1=time.time()
# With more iterations it will be more likely that we hit a already cached row
inds=np.random.randint(0, high=shape[0]-1, size=1000)
for i in xrange(0,inds.shape[0]):
Array=np.copy(d[inds[i],:])
print(time.time()-t1)
f.close()
if __name__ == "__main__":
ReadingAndWriting()

花式切片的最简单形式

我在评论中写道,在最近的版本中我看不到这种行为。我错了。比较以下各项:

^{pr2}$

在我的SSD上,第一个版本为10.8秒,第二个版本为55秒。在