C++从HDF5读取单个向量报错问题求助
问题描述
我有一份HDF5格式的数据,形状为(10000, 100),也就是10000个包含100个float的向量。我想要把这些数据提取到C++的vector中,最终得到一个包含10000个元素的vector,每个元素又是包含100个float的vector。
我尝试创建一个包含100个元素的一维内存空间(memspace),然后从文件数据集里逐行读取到内存中,但一直报错:
#001: ../../../src/H5Dio.c line 487 in H5D__read(): src and dest dataspaces have different number of elements selected
我的代码如下:
H5File fp(... , H5F_ACC_RDONLY); DataSet dset = fp.openDataSet("/dataset"); DataSpace dspace = dset.getSpace(); hsize_t rank; hsize_t dims[2]; rank = dspace.getSimpleExtentDims(dims, NULL); cout<<"Datasize: " << dims[0] << endl; // Define the memory dataspace hsize_t dimsm[1]; dimsm[0] = dims[1]; DataSpace memspace (1, dimsm); // create a vector the same size as the dataset vector<vector<float>> data; data.resize(dims[0]); for (hsize_t i = 0; i < dims[0]; i++) { data[i].resize(dims[1]); } //cout<<"Vectsize: "<< data.size() <<endl; // Initialize hyperslabs hsize_t dataCount[1] = {0,}; hsize_t dataOffset[1] = {0,}; hsize_t memCount[1] = {0,}; hsize_t memOffset[1] = {0,}; for (hsize_t i = 0; i < dims[0]; i++) { dataOffset[0] = i; dataCount[0] = dims[1]; memOffset[0] = 0; memCount[0] = dims[1]; dspace.selectHyperslab(H5S_SELECT_SET, dataCount, dataOffset); memspace.selectHyperslab(H5S_SELECT_SET, memCount, memOffset); dset.read(data[i].data(), PredType::IEEE_F32LE, memspace, dspace); printf("OK %d\n", (int)i); }
问题原因与修复
报错核心原因是:数据集的dataspace是二维结构,但你用一维参数选择hyperslab,导致选中的元素数量与内存空间不匹配。
原代码中,dspace对应HDF5里的二维数据集(10000,100),但初始化的dataCount和dataOffset是一维数组,调用selectHyperslab时HDF5会按一维逻辑解析二维空间,实际选中的元素数量和内存侧的100个元素不匹配,触发错误。
修复后的代码
H5File fp(... , H5F_ACC_RDONLY); DataSet dset = fp.openDataSet("/dataset"); DataSpace dspace = dset.getSpace(); hsize_t rank; hsize_t dims[2]; rank = dspace.getSimpleExtentDims(dims, NULL); cout << "Datasize: " << dims[0] << endl; // 内存空间保持一维(对应单个100元素的向量) hsize_t dimsm[1] = {dims[1]}; DataSpace memspace(1, dimsm); // 初始化二维hyperslab参数,匹配数据集的二维结构 hsize_t dataCount[2] = {1, dims[1]}; // 每次选1行,每行100个元素 hsize_t dataOffset[2] = {0, 0}; hsize_t memCount[1] = {dims[1]}; hsize_t memOffset[1] = {0}; // 直接初始化二维vector,简化代码 vector<vector<float>> data(dims[0], vector<float>(dims[1])); for (hsize_t i = 0; i < dims[0]; i++) { dataOffset[0] = i; // 切换到第i行 // 对二维dspace选择hyperslab:从(i,0)开始,选1行×100列 dspace.selectHyperslab(H5S_SELECT_SET, dataCount, dataOffset); // 内存空间选中整个一维区域 memspace.selectHyperslab(H5S_SELECT_SET, memCount, memOffset); dset.read(data[i].data(), PredType::IEEE_F32LE, memspace, dspace); printf("OK %d\n", (int)i); }
关键修正点
- 数据集hyperslab参数改为二维:
dataCount设为{1, dims[1]},表示每次选择1行、每行全部100个元素;dataOffset设为{i, 0},定位到第i行起始位置。 - 简化vector初始化:用
vector<vector<float>> data(dims[0], vector<float>(dims[1]))一次性完成二维vector的空间分配,避免循环resize。 - 元素数量匹配:数据集侧每次选1×100=100个元素,内存侧选1×100=100个元素,数量一致即可解决报错。
额外优化建议
如果数据量允许,一次性读取整个数据集到连续内存再拆分,效率更高:
// 一次性读取所有数据到一维vector vector<float> flat_data(dims[0] * dims[1]); dset.read(flat_data.data(), PredType::IEEE_F32LE); // 拆分到二维vector vector<vector<float>> data(dims[0], vector<float>(dims[1])); for (hsize_t i = 0; i < dims[0]; i++) { memcpy(data[i].data(), &flat_data[i * dims[1]], dims[1] * sizeof(float)); }
内容的提问来源于stack exchange,提问作者MoonDrop legacy
相关产品推荐
相关产品推荐

