HDF5 H5Dread内存使用过多

Excessive Memory use with HDF5 H5Dread

本文关键字:H5Dread 内存 HDF5      更新时间:2023-10-16

我们的程序因使用过多内存而崩溃。这是HDF5 1.8.9。

大多数时候,我们没有问题,但有时对于较大的文件,会发生以下情况:

在这个例子中,我有一个325MB的HDF5文件,这导致2GB的内存被用来读取它的一些值(HDF5文件中数据点的"时间步长",只有400001个双精度值)。看来是我们使用H5Dread方法造成了问题。你知道我们做错了什么吗?

导致问题的方法如下:

std::vector<double> Hdf5DataReader::GetUnlimitedDimensionValues() 
{ 
    // Define hyperslab in the dataset 
    hid_t time_dataspace = H5Dget_space(mUnlimitedDatasetId); 
    // Get the dataset/dataspace dimensions
    hsize_t num_timesteps;
    H5Sget_simple_extent_dims(time_dataspace, &num_timesteps, NULL);
    // Data buffer to return 
    std::cout << "Number of timesteps we are reserving memory for = " << num_timesteps << "n"; 
    std::vector<double> ret(num_timesteps);         
    PrintMemoryUsage("made memory space"); 
    // Read data from hyperslab in the file into the hyperslab in memory 
    H5Dread(mUnlimitedDatasetId, 
            H5T_NATIVE_DOUBLE, 
            H5S_ALL, 
            H5S_ALL, 
            H5P_DEFAULT, 
            &ret[0]); 
    PrintMemoryUsage("read into memory space"); 
    H5Sclose(time_dataspace); 
    return ret; 
} 

输出为

Number of timesteps we are reserving memory for = 400001
made memory space: memory use = 43.5898 MB.
read into memory space: memory use = 2182.4 MB.

(使用此代码来诊断分配给程序的内存量-这看起来合理吗?:

#include <unistd.h>
#include <sys/resource.h>
void PrintMemoryUsage(const std::string& rPrefix)
{
    struct rusage rusage;
    getrusage( RUSAGE_SELF, &rusage );
    double max_res = (double)(rusage.ru_maxrss)/(1024);// Convert KB to MB
    std::cout << rPrefix << ": memory use = " << max_res <<  " MB.n";
}

)

Yossarian的评论包含了线索——虽然我们检查了主数据集的分块,但内存爆炸实际上来自一个只包含时间值的关联1D数据集。后一个数据集的块大小为1。增加区块大小解决了问题。

我也遇到了同样的问题。在我的案例中,这是因为数据集的维度是无限的(正如Yossarian所提到的)。

为了验证错误,我创建了两个版本的数据集:一个是无限维度长度,另一个是固定维度长度。这两个数据集都有相同的数据。内存消耗随着无限量的增加而激增,而使用恒定长度创建的数据集则没有任何问题。

还有一件事要提:我的原始数据集是由旧版本的NetCDF创建的,我使用"nccopy-k4"将其转换为NetCDF4/HDF5格式。