用于读取行的最佳HDF5数据集块形状

用于读取行的最佳HDF5数据集块形状,第1张

用于读取行的最佳HDF5数据集块形状

找到正确的块缓存大小

首先,我想讨论一些一般性的事情。知道每个单独的块只能整体读取或写入非常重要。默认情况下,可以避免过多的磁盘I /
O的h5py的标准块高速缓存大小仅为默认值1 MB,并且在许多情况下应该增加该大小,稍后将对此进行讨论。

举个例子:

  • 我们有一个形状为(639038,10000),float32(未压缩的25.5 GB)的dset
  • 我们想按列写数据,
    dset[:,i]=arr
    并按行读数据
    arr=dset[i,:]
  • 我们为这种类型的工作选择了完全错误的块形状,即(1,10000)

在这种情况下,读取速度不会很差(尽管块大小有点小),因为我们只读取正在使用的数据。但是,当我们在该数据集上书写时会发生什么呢?如果我们访问列,则会写入每个块的一个浮点数。这意味着我们实际上每次迭代都会写入整个数据集(25.5
GB),并每隔一段时间读取一次整个数据集。这是因为如果您修改了一个块,那么如果它没有被缓存,则必须首先读取它(我假设这里的chunk-cache-
size小于25.5 GB)。

那么我们在这里可以改善什么呢?在这种情况下,我们必须在写入/读取速度与块缓存使用的内存之间做出折衷。

假设将给出不错的读/写速度:

  • 我们选择(100,1000)的块大小
  • 如果我们要遍历第一维,则至少需要(1000 * 639038 * 4-> 2,55 GB)高速缓存,以避免如上所述的额外IO开销和(100 * 10000 * 4-> 0.4 MB) 。
  • 因此,在此示例中,我们至少应提供2.6 GB的块数据缓存。

结论
通常没有合适的块大小或形状,这在很大程度上取决于要使用的任务。切勿在不考虑块缓存的情况下选择块的大小或形状。就随机读/写而言,RAM比最快的SSD快了几个数量级。

关于您的问题, 我只会读取随机行,不正确的chunk-cache-size是您真正的问题。

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

import h5py as h5import timeimport numpy as npdef ReadingAndWriting():    File_Name_HDF5='Test.h5'    #shape = (639038, 10000)    shape = (639038, 1000)    chunk_shape=(100, 1000)    Array=np.array(np.random.rand(shape[0]),np.float32)    #We are using 4GB of chunk_cache_mem here ("rdcc_nbytes")    f = h5.File(File_Name_HDF5, 'w',rdcc_nbytes =1024**2*4000,rdcc_nslots=1e7)    d = f.create_dataset('Test', shape ,dtype=np.float32,chunks=chunk_shape,compression="lzf")    #Writing columns    t1=time.time()    for i in range(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 = h5.File(File_Name_HDF5,'r',rdcc_nbytes=1024**2*4000,rdcc_nslots=1e7)    d = f["Test"]    for j in range(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 range(0,inds.shape[0]): Array=np.copy(d[inds[i],:])        print(time.time()-t1)    f.close()

花式切片的最简单形式

我在评论中写道,在最新版本中看不到这种现象。我错了。比较以下内容:

def Writing():File_Name_HDF5 =’Test.h5’

#shape = (639038, 10000)shape = (639038, 1000)chunk_shape=(100, 1000)Array=np.array(np.random.rand(shape[0]),np.float32)# Writing_1 normal indexing###########################################f = h5c.File(File_Name_HDF5, 'w',chunk_cache_mem_size=1024**2*4000)d = f.create_dataset('Test', shape ,dtype=np.float32,chunks=chunk_shape,compression="lzf")t1=time.time()for i in range(shape[1]):    d[:,i:i+1]=np.expand_dims(Array, 1)f.close()print(time.time()-t1)# Writing_2 simplest form of fancy indexing###########################################f = h5.File(File_Name_HDF5, 'w',rdcc_nbytes =1024**2*4000,rdcc_nslots=1e7)d = f.create_dataset('Test', shape ,dtype=np.float32,chunks=chunk_shape,compression="lzf")#Writing columnst1=time.time()for i in range(shape[1]):    d[:,i]=Arrayf.close()print(time.time()-t1)

对于我的硬盘,第一个版本为34秒,第二个版本为78秒。



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/4947663.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-13
下一篇 2022-11-13

发表评论

登录后才能评论

评论列表(0条)

保存