问题:我有现有的netCDF4文件(其中大约有5000个),(通常为96x3712x3712)数据点(float32)。这些文件的第一个维度是时间(每天一个文件),第二个和第三个空间维度。目前,由于以下原因,在第一维度(甚至部分切片)上创建一个切片将花费大量时间:
我的目标是:
其他所需经费:
我已经尝试了多种方法:
下面是创建一个月文件的代码:
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稍多一点)。怎么会花这么长时间?我做错了什么?如果有人能照亮幕后的真相,我会很高兴的.
发布于 2017-07-07 01:32:38
块大小对的影响
在最坏的情况下,读和写一个块可以被看作是随机读/写操作。SSD的主要优点是读取或写入小块数据的速度。在这个任务中,HDD要慢得多(可以观察到因子100 ),NAS甚至可以比HDD慢得多。
所以解决这个问题的方法是更大的块大小。我的系统上的一些基准(核心i5-4690)。
Exampe_1 (块大小(1,29,29)=3,4 kB):
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):
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较慢,但提供了更好的压缩比。
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)编写的。
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上访问数据时,我也遇到了同样的问题。希望这能帮上忙..。
https://stackoverflow.com/questions/44881895
复制相似问题