我建议不要分块数据,而是将数据存储为一系列单个数组数据集(按照Benjamin的建议)。我刚刚将一个企业应用程序的输出加载到HDF5中,并能够将大约45亿个复合数据类型打包成45万个数据集,每个集合包含10000个数据的数组。现在写入和读取似乎非常快速,在我最初尝试分块数据时速度非常慢。这只是我的一些想法!
更新:
以下是我实际代码中提取的几个片段(我正在使用C而不是Python进行编码,但您应该了解我正在做什么)。我只是在数组中写入长无符号整数(每个数组有10000个值),并在需要实际值时将它们读回来。
这是我的典型编写器代码。在这种情况下,我只是将长无符号整数序列写入一个数组序列中,并在创建每个数组序列时将其加载到HDF5中。
long unsigned int k = 0UL;
long unsigned int kValues[NUMPERDATASET];
hid_t ssdb = H5Fcreate(SSHDF, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
hsize_t dsDim[1] = {NUMPERDATASET};
hid_t dSpace = H5Screate_simple(1, dsDim, NULL);
for (unsigned long int i = 0UL; i < NUMDATASETS; i++){
for (unsigned long int j = 0UL; j < NUMPERDATASET; j++){
kValues[j] = k;
k += 1UL;
}
dssSet = H5Dcreate2(ssdb, g_strdup_printf("%lu", i), H5T_NATIVE_ULONG, dSpace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
H5Dwrite(dssSet, H5T_NATIVE_ULONG, H5S_ALL, H5S_ALL, H5P_DEFAULT, kValues);
H5Dclose(dssSet);
}
H5Sclose(dSpace);
H5Fclose(ssdb);
这是我读取代码的稍作修改版。有更优雅的做法(例如,可以使用超平面来获取值),但这是相对于我遵循的较为严谨的敏捷/BDD开发流程而言最干净的解决方案。
unsigned long int getValueByIndex(unsigned long int nnValue){
unsigned long int ssValue[NUMPERDATASET];
unsigned long int i = MIN(MAXSSVALUE-1,nnValue);
hid_t db = H5Fopen(_indexFilePath, H5F_ACC_RDONLY, H5P_DEFAULT);
hid_t dSet = H5Dopen(db, g_strdup_printf("%lu", i / NUMPERDATASET), H5P_DEFAULT);
H5Dread(dSet, H5T_NATIVE_ULONG, H5S_ALL, H5S_ALL, H5P_DEFAULT, ssValue);
H5Dclose(dSet);
H5Fclose(db);
return ssValue[i % NUMPERDATASET];
}
主要是写入代码的内部循环、整数除法和模运算来获取数据集数组中所需值的索引。如果理解清楚了,您可以在h5py中整合类似或更好的代码。在C语言中,这很简单,而且读写时间显著优于分块数据集解决方案。另外,由于无法对复合数据集使用压缩,因此分块的表面优势是无效的,因此所有复合数据都以相同方式存储。