存储、写入和读取大型气象数据集的更好方法
A better approach to store, write, and read a big dataset of meteorological data
我希望能更好地存储、写入和读取气象数据(原始文本格式约 30 GB)。
目前我正在使用NetCDF 文件格式来存储天气记录。在这个 NetCDF 文件中,我有 3 个维度:time
、climate variables
、locations
。但是维度顺序是我的任务的关键约束(见下文)。
第一个任务是每天更新大约3000个气象站的天气记录。维度顺序 (time, var, name)
提供最佳写入性能,因为新数据将添加到 NetCDF 文件的末尾。
第二个任务是读取站点的所有每日天气记录以进行分析。维度顺序 (name, var, time)
提供了最佳的读取性能,因为一个站点的所有记录都存储在一起。
两个任务有NetCDF文件的冲突设计(一个任务性能最好,另一个任务性能最差)。
我的问题是是否有替代 methods/software/data 格式来存储、写入和读取我的数据集以提供我的两项任务的最佳性能?由于我每天都要重复这两个步骤,而且数据分析很耗时,我需要找到一个最好的方法来最小化 I/O.
感谢您的任何建议。如果我的问题不清楚,请告诉我。
好的,您需要的是分块。我创建了一个小的 python 脚本来测试,没有分块,它基本上证实了您的观察,即一维访问速度很慢。我测试了站号 3000,每个站的变量 10 和时间步长 10000。我确实将站和变量放入相同的维度进行测试,但如果你真的需要它,它应该在 3D 情况下给出类似的结果。
我没有分块的测试输出:
File chunking type: None
Variable shape: (30000, 10000)
Total time, file creation: 13.665503025054932
Average time for adding one measurement time: 0.00136328568459 0.00148195505142 0.0018851685524
Read all timeseries one by one with single file open
Average read time per station/variable: 0.524109539986
并使用分块:
File chunking type: [100, 100]
Variable shape: (30000, 10000)
Total time, file creation: 18.610711812973022
Average time for adding one measurement time: 0.00185681316853 0.00168470859528 0.00213300466537
Read all timeseries one by one with single file open
Average read time per station/variable: 0.000948731899261
您可以看到,分块将写入时间增加了大约 50%,但显着缩短了读取时间。我没有尝试优化块大小,只是测试它在正确的方向上工作。
如果代码不清楚或您不熟悉 python.
,请随时询问
# -*- coding: utf-8 -*-
from time import time
import numpy as np
from netCDF4 import Dataset
test_dataset_name='test_dataset.nc4'
num_stations=3000
num_vars=10
chunks=None
#chunks=[100,100]
def create_dataset():
ff=Dataset(test_dataset_name,'w')
ff.createDimension('Time',None)
ff.createDimension('Station_variable',num_stations*num_vars)
if chunks:
var1=ff.createVariable('TimeSeries','f8', ('Station_variable','Time'),chunksizes=chunks)
else:
var1=ff.createVariable('TimeSeries','f8',('Station_variable','Time'))
return ff
def add_data(ff,timedim):
var1=ff.variables['TimeSeries']
var1[0:1000,timedim]=timedim*np.ones((1000),'f8')
def dataset_close(inds):
inds.close()
## CREATE DATA FILE
time_start=time()
time1=[]
time2=[]
time3=[]
time4=[]
testds=create_dataset()
dataset_close(testds)
for i in range(10000):
time1.append(time())
ff=Dataset(test_dataset_name,'a')
time2.append(time())
add_data(ff,i)
time3.append(time())
ff.sync()
ff.close()
time4.append(time())
time_end=time()
time1=np.array(time1)
time2=np.array(time2)
time3=np.array(time3)
time4=np.array(time4)
## READ ALL STAION-VARIABLE COMBINATIONS AS ONE TIMESERIES
ff=Dataset(test_dataset_name,'r')
## PRINT DATA FILE CREATION SUMMARY
print("File chunking type:",chunks)
print("Variable shape:",ff.variables['TimeSeries'][:].shape)
print("Total time, file creation:", time_end-time_start)
print("Average time for adding one measurement time: ",np.mean(time4- time1), np.mean(time4[:100]-time1[:100]),np.mean(time4[-100:]- time1[-100:]))
print("Read all timeseries one by one with single file open")
time_rstart=[]
time_rend=[]
for i in range(0,ff.variables['TimeSeries'][:].shape[0],int(ff.variables['TimeSeries'][:].shape[0]/100)):
time_rstart.append(time())
dataline=ff.variables['TimeSeries'][i,:]
time_rend.append(time())
time_rstart=np.array(time_rstart)
time_rend=np.array(time_rend)
print("Average read time per station/variable: ",np.mean(time_rend- time_rstart))
我希望能更好地存储、写入和读取气象数据(原始文本格式约 30 GB)。
目前我正在使用NetCDF 文件格式来存储天气记录。在这个 NetCDF 文件中,我有 3 个维度:time
、climate variables
、locations
。但是维度顺序是我的任务的关键约束(见下文)。
第一个任务是每天更新大约3000个气象站的天气记录。维度顺序 (time, var, name)
提供最佳写入性能,因为新数据将添加到 NetCDF 文件的末尾。
第二个任务是读取站点的所有每日天气记录以进行分析。维度顺序 (name, var, time)
提供了最佳的读取性能,因为一个站点的所有记录都存储在一起。
两个任务有NetCDF文件的冲突设计(一个任务性能最好,另一个任务性能最差)。
我的问题是是否有替代 methods/software/data 格式来存储、写入和读取我的数据集以提供我的两项任务的最佳性能?由于我每天都要重复这两个步骤,而且数据分析很耗时,我需要找到一个最好的方法来最小化 I/O.
感谢您的任何建议。如果我的问题不清楚,请告诉我。
好的,您需要的是分块。我创建了一个小的 python 脚本来测试,没有分块,它基本上证实了您的观察,即一维访问速度很慢。我测试了站号 3000,每个站的变量 10 和时间步长 10000。我确实将站和变量放入相同的维度进行测试,但如果你真的需要它,它应该在 3D 情况下给出类似的结果。 我没有分块的测试输出:
File chunking type: None
Variable shape: (30000, 10000)
Total time, file creation: 13.665503025054932
Average time for adding one measurement time: 0.00136328568459 0.00148195505142 0.0018851685524
Read all timeseries one by one with single file open
Average read time per station/variable: 0.524109539986
并使用分块:
File chunking type: [100, 100]
Variable shape: (30000, 10000)
Total time, file creation: 18.610711812973022
Average time for adding one measurement time: 0.00185681316853 0.00168470859528 0.00213300466537
Read all timeseries one by one with single file open
Average read time per station/variable: 0.000948731899261
您可以看到,分块将写入时间增加了大约 50%,但显着缩短了读取时间。我没有尝试优化块大小,只是测试它在正确的方向上工作。 如果代码不清楚或您不熟悉 python.
,请随时询问# -*- coding: utf-8 -*-
from time import time
import numpy as np
from netCDF4 import Dataset
test_dataset_name='test_dataset.nc4'
num_stations=3000
num_vars=10
chunks=None
#chunks=[100,100]
def create_dataset():
ff=Dataset(test_dataset_name,'w')
ff.createDimension('Time',None)
ff.createDimension('Station_variable',num_stations*num_vars)
if chunks:
var1=ff.createVariable('TimeSeries','f8', ('Station_variable','Time'),chunksizes=chunks)
else:
var1=ff.createVariable('TimeSeries','f8',('Station_variable','Time'))
return ff
def add_data(ff,timedim):
var1=ff.variables['TimeSeries']
var1[0:1000,timedim]=timedim*np.ones((1000),'f8')
def dataset_close(inds):
inds.close()
## CREATE DATA FILE
time_start=time()
time1=[]
time2=[]
time3=[]
time4=[]
testds=create_dataset()
dataset_close(testds)
for i in range(10000):
time1.append(time())
ff=Dataset(test_dataset_name,'a')
time2.append(time())
add_data(ff,i)
time3.append(time())
ff.sync()
ff.close()
time4.append(time())
time_end=time()
time1=np.array(time1)
time2=np.array(time2)
time3=np.array(time3)
time4=np.array(time4)
## READ ALL STAION-VARIABLE COMBINATIONS AS ONE TIMESERIES
ff=Dataset(test_dataset_name,'r')
## PRINT DATA FILE CREATION SUMMARY
print("File chunking type:",chunks)
print("Variable shape:",ff.variables['TimeSeries'][:].shape)
print("Total time, file creation:", time_end-time_start)
print("Average time for adding one measurement time: ",np.mean(time4- time1), np.mean(time4[:100]-time1[:100]),np.mean(time4[-100:]- time1[-100:]))
print("Read all timeseries one by one with single file open")
time_rstart=[]
time_rend=[]
for i in range(0,ff.variables['TimeSeries'][:].shape[0],int(ff.variables['TimeSeries'][:].shape[0]/100)):
time_rstart.append(time())
dataline=ff.variables['TimeSeries'][i,:]
time_rend.append(time())
time_rstart=np.array(time_rstart)
time_rend=np.array(time_rend)
print("Average read time per station/variable: ",np.mean(time_rend- time_rstart))