首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >h5py不坚持分块规范吗?

h5py不坚持分块规范吗?
EN

Stack Overflow用户
提问于 2017-07-03 09:18:28
回答 1查看 1.3K关注 0票数 2

问题:我有现有的netCDF4文件(其中大约有5000个),(通常为96x3712x3712)数据点(float32)。这些文件的第一个维度是时间(每天一个文件),第二个和第三个空间维度。目前,由于以下原因,在第一维度(甚至部分切片)上创建一个切片将花费大量时间:

  • netCDF文件块大小为1x3712x3712。切分时间维度基本上会读取整个文件。
  • 在所有较小的文件上循环(即使在多个进程中)也需要很长时间。

我的目标是:

  • 创建每月文件(约2900x3712x3712)数据点
  • 优化时间尺寸(块状尺寸2900x1x1或空间尺寸稍大)

其他所需经费:

  • 文件应由单个时间戳(1x3712x3712)附加,此更新过程应少于15分钟。
  • 查询应该足够快:在不到1秒(即2900x1x1)的时间内,一个完整的数据片段(==>)实际上不是那么多数据.
  • 最好文件在更新时可供多个进程读取。
  • 处理历史数据(其他5000份每日文件)应花费不到几个星期,最好是。

我已经尝试了多种方法:

  • 连接netcdf文件和重块them==>需要太多内存和时间.
  • 将它们从熊猫写入hdf文件(使用pytable),==>会创建一个包含巨大索引的宽表。这最终也将花费太多的时间来读取,并且由于元数据约束,需要在空间维度上平铺数据集。
  • 我的最后一种方法是使用hdf5将它们写入一个h5py文件:

下面是创建一个月文件的代码:

代码语言:javascript
运行
复制
import h5py
import pandas as pd
import numpy as np

def create_h5(fps):
    timestamps=pd.date_range("20050101",periods=31*96,freq='15T') #Reference time period
    output_fp = r'/data/test.h5'
    try:
        f = h5py.File(output_fp, 'a',libver='latest')
        shape = 96*nodays, 3712, 3712
        d = f.create_dataset('variable', shape=(1,3712,3712), maxshape=(None,3712,3712),dtype='f', compression='gzip', compression_opts=9,chunks=(1,29,29))
        f.swmr_mode = True
        for fp in fps:
            try:
                nc=Dataset(fp)
                times = num2date(nc.variables['time'][:], nc.variables['time'].units)
                indices=np.searchsorted(timestamps, times)
                for j,time in enumerate(times):
                    logger.debug("File: {}, timestamp: {:%Y%m%d %H:%M}, pos: {}, new_pos: {}".format(os.path.basename(fp),time,j,indices[j]))
                    d.resize((indices[j]+1,shape[1],shape[2]))
                    d[indices[j]]=nc.variables['variable'][j:j+1]
                    f.flush()
            finally:
                nc.close()
    finally:
        f.close()
    return output_fp

我正在使用HDF5的最后一个版本来使用SWMR选项。fps参数是每日netCDF4文件的文件路径列表。它在大约2小时内创建文件(在ssd上,但我看到创建文件主要是CPU绑定的),这是可以接受的。

我设置了压缩以使文件大小保持在限制范围内。我之前做了一些没有的测试,并且看到没有的创建要快一些,但是切片并不需要太多的压缩时间。H5py自动将数据集块分成1x116x116块。

现在的问题是:使用RAID 6设置在NAS上切片,分割时间维度大约需要20秒,即使它在一个块中.

我想,即使它在文件中的单个块中,因为我在一个循环中编写了所有的值,但它必须是分段的(尽管不知道这个过程是如何工作的)。这就是为什么我试图使用CML工具将h5repack转换为一个新文件的原因,该文件具有相同的块,但希望能够重新排序这些值,以便查询能够以更连续的顺序读取值,但没有运气。尽管这个过程需要6小时才能运行,但它在查询速度上没有做任何事情。

如果我的计算正确,读取一个块(2976x32x32)只会有几MB大(11 MB未压缩,比我认为的压缩1MB稍多一点)。怎么会花这么长时间?我做错了什么?如果有人能照亮幕后的真相,我会很高兴的.

EN

回答 1

Stack Overflow用户

发布于 2017-07-07 01:32:38

块大小对的影响

在最坏的情况下,读和写一个块可以被看作是随机读/写操作。SSD的主要优点是读取或写入小块数据的速度。在这个任务中,HDD要慢得多(可以观察到因子100 ),NAS甚至可以比HDD慢得多。

所以解决这个问题的方法是更大的块大小。我的系统上的一些基准(核心i5-4690)。

Exampe_1 (块大小(1,29,29)=3,4 kB):

代码语言:javascript
运行
复制
import numpy as np
import tables #needed for blosc
import h5py as h5
import time
import h5py_cache as h5c

def original_chunk_size():
    File_Name_HDF5='some_Path'
    #Array=np.zeros((1,3712,3712),dtype=np.float32)
    Array=np.random.rand(96,3712,3712)

    f = h5.File(File_Name_HDF5, 'a',libver='latest')
    f.swmr_mode = True
    nodays=1

    shape = 96*nodays, 3712, 3712
    d = f.create_dataset('variable', shape, maxshape=(None,3712,3712),dtype='f',chunks=(1,29,29),compression=32001,compression_opts=(0, 0, 0, 0, 9, 1, 1), shuffle=False)

    #Writing
    t1=time.time()
    for i in xrange(0,96*nodays):
        d[i:i+1,:,:]=Array

    f.close()
    print(time.time()-t1)

    #Reading
    f = h5.File(File_Name_HDF5, 'a',libver='latest')
    f.swmr_mode = True
    d=f['variable']

    for i in xrange(0,3712,29):
        for j in xrange(0,3712,29):
            A=np.copy(d[:,i:i+29,j:j+29])

    print(time.time()-t1)

结果(写/读):

社会福利署: 38s/54s

HDD: 40/57s

NAS: 252 s/823 s

在第二个例子中,我将使用h5py_chache,因为我不想维护(1,3712,3712)的块。标准的块-chache大小仅为1 MB,因此必须对其进行更改,以避免对块进行多次读/写操作。https://pypi.python.org/pypi/h5py-cache/1.0

Exampe_2 (块大小(96,58,58)=1,3 MB):

代码语言:javascript
运行
复制
import numpy as np
import tables #needed for blosc
import h5py as h5
import time
import h5py_cache as h5c

def modified_chunk_size():
    File_Name_HDF5='some_Path'
    Array=np.random.rand(1,3712,3712)

    f = h5c.File(File_Name_HDF5, 'a',libver='latest', 
    chunk_cache_mem_size=6*1024**3)
    f.swmr_mode = True
    nodays=1

    shape = 96*nodays, 3712, 3712
    d = f.create_dataset('variable', shape, maxshape=(None,3712,3712),dtype='f',chunks=(96,58,58),compression=32001,compression_opts=(0, 0, 0, 0, 9, 1, 1), shuffle=False)

    #Writing
    t1=time.time()
    for i in xrange(0,96*nodays):
        d[i:i+1,:,:]=Array

    f.close()
    print(time.time()-t1)

    #Reading
    f = h5c.File(File_Name_HDF5, 'a',libver='latest', chunk_cache_mem_size=6*1024**3) #6 GB chunk chache
    f.swmr_mode = True
    d=f['variable']

    for i in xrange(0,3712,58):
        for j in xrange(0,3712,58):
            A=np.copy(d[:,i:i+58,j:j+58])

    print(time.time()-t1)

结果(写/读):

社会服务电子化: 10s/16s

HDD: 10s/16s

NAS: 13S/20

通过最小化api调用(读取和写入较大的块块),可以进一步提高读/写速度。

我也不想提她的压缩方法。Blosc可以达到1GB/s的吞吐量(CPU瓶颈) gzip较慢,但提供了更好的压缩比。

代码语言:javascript
运行
复制
d = f.create_dataset('variable', shape, maxshape=(None,3712,3712),dtype='f',chunks=(96,58,58),compression='gzip', compression_opts=3)

文件大小: 101 MB

D=f.create_dataset(“变量”,形状,maxshape=(无,3712,3712),dtype='f',chunks=(96,58,58),压缩=‘gzip’,compression_opts=6)

50/58s文件大小: 87 MB

D=f.create_dataset(“变量”,形状,maxshape=(无,3712,3712),dtype='f',chunks=(96,58,58),压缩=‘gzip’,compression_opts=9)

50/60文件大小: 64 MB

现在是整个月(30天)的基准。编写过程有一点优化,是用(96,3712,3712)编写的。

代码语言:javascript
运行
复制
def modified_chunk_size():
    File_Name_HDF5='some_Path'

    Array_R=np.random.rand(1,3712,3712)
    Array=np.zeros((96,3712,3712),dtype=np.float32)
    for j in xrange(0,96):
        Array[j,:,:]=Array_R

    f = h5.File(File_Name_HDF5, 'a',libver='latest')
    f.swmr_mode = True
    nodays=30

    shape = 96, 3712, 3712
    d = f.create_dataset('variable', shape, maxshape=(None,3712,3712),dtype='f',chunks=(96,58,58),compression=32001,compression_opts=(0, 0, 0, 0, 9, 1, 1), shuffle=False)

    #Writing
    t1=time.time()
    for i in xrange(0,96*nodays,96):
        d[i:i+96,:,:]=Array
        d.resize((d.shape[0]+96,shape[1],shape[2]))

    f.close()
    print(time.time()-t1)

    #Reading
    f = h5.File(File_Name_HDF5, 'a',libver='latest')
    f.swmr_mode = True
    d=f['variable']
    for i in xrange(0,3712,58):
        for j in xrange(0,3712,58):
            A=np.copy(d[:,i:i+58,j:j+58])

    print(time.time()-t1)

133 s/301 s(带blosc )

带gzip compression_opts=3的432 s/684 s

在NAS上访问数据时,我也遇到了同样的问题。希望这能帮上忙..。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44881895

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档