【问题标题】:Single array in the hdf5 filehdf5 文件中的单个数组
【发布时间】:2016-09-11 18:51:40
【问题描述】:

我的数据集的图像:

我正在使用带有 C# 的 HDF5DotNet,我只能读取完整数据作为数据集中的附加图像。 hdf5文件太大了,将近10GB,如果我把整个数组加载到内存中就会内存不足。

我想读取附图中第 5 行和第 7 行的所有数据。无论如何一次只将这两行数据读入内存,而不必先将所有数据加载到内存中?

    private static void OpenH5File()
    {

        var h5FileId = H5F.open(@"D:\Sandbox\Flood Modeller\Document\xmdf_results\FMA_T1_10ft_001.xmdf", H5F.OpenMode.ACC_RDONLY);
        string dataSetName = "/FMA_T1_10ft_001/Temporal/Depth/Values";
        var dataset = H5D.open(h5FileId, dataSetName);
        var space = H5D.getSpace(dataset);
        var dataType = H5D.getType(dataset);

        long[] offset = new long[2];
        long[] count = new long[2];
        long[] stride = new long[2];
        long[] block = new long[2];

        offset[0] = 1;     // start at row 5
        offset[1] = 2;     // start at column 0

        count[0] = 2;      // read 2 rows
        count[0] = 165701; // read all columns

        stride[0] = 0;     // don't skip anything
        stride[1] = 0;

        block[0] = 1;      // blocks are single elements
        block[1] = 1;

        // Dataspace associated with the dataset in the file
        // Select a hyperslab from the file dataspace
        H5S.selectHyperslab(space, H5S.SelectOperator.SET, offset, count, block);
        // Dimensions of the file dataspace
        var dims = H5S.getSimpleExtentDims(space);

        // We also need a memory dataspace which is the same size as the file dataspace
        var memspace = H5S.create_simple(2, dims);

        double[,] dataArray = new double[1, dims[1]]; // just get one array
        var wrapArray = new H5Array<double>(dataArray);

        // Now we can read the hyperslab
        H5D.read(dataset, dataType, memspace, space,
                 new H5PropertyListId(H5P.Template.DEFAULT), wrapArray);

    }

【问题讨论】:

    标签: hdf5


    【解决方案1】:

    您需要选择具有正确 offsetcountstrideblock 的 hyperslab您希望读取的数据集的子集。这些都是与您的数据集具有相同维数的数组。
    block 是要读取的每个维度中元素块的大小,即 1 是单个元素。
    offset是从数据集开始到开始读取的blocks个数,countblocks个数em> 阅读。
    您可以使用 stride 选择不连续的区域,它再次计入 blocks

    恐怕我不懂 C#,所以下面是 C 语言。在你的例子中,你会:

    hsize_t offset[2], count[2], stride[2], block[2];
    
    offset[0] = 5;     // start at row 5
    offset[1] = 0;     // start at column 0
    
    count[0] = 2;      // read 2 rows
    count[1] = 165702; // read all columns
    
    stride[0] = 1;     // don't skip anything
    stride[1] = 1;
    
    block[0] = 1;      // blocks are single elements
    block[1] = 1;
    
    // This assumes you already have an open dataspace with ID dataspace_id
    H5Sselect_hyperslab(dataspace_id, H5S_SELECT_SET, offset, stride, count, block)
    

    您可以在HDF5 tutorial 中找到更多关于读/写 hyperslab 的信息。


    在 C# 中似乎有两种形式的H5D.read,你想要second form

    H5D.read(Type) Method (H5DataSetId, H5DataTypeId, H5DataSpaceId,
                           H5DataSpaceId, H5PropertyListId, H5Array(Type))
    

    这允许您指定内存和文件数据空间。本质上,您需要一个数据空间,其中包含您要读取的内存中变量的大小、步幅、偏移量等信息;以及您要从中读取的文件中的数据集的一个数据空间。这使您可以执行诸如从文件中的非连续区域读取到内存中数组中的连续区域之类的操作。

    你想要类似的东西

    // Dataspace associated with the dataset in the file
    var dataspace = H5D.get_space(dataset);
    // Select a hyperslab from the file dataspace
    H5S.selectHyperslab(dataspace, H5S.SelectOperator.SET, offset, count);
    // Dimensions of the file dataspace
    var dims = H5S.getSimpleExtentDims(dataspace);
    // We also need a memory dataspace which is the same size as the file dataspace
    var memspace = H5S.create_simple(rank, dims);
    
    // Now we can read the hyperslab
    H5D.read(dataset, datatype, memspace, dataspace, 
             new H5PropertyListId(H5P.Template.DEFAULT), wrapArray);
    

    从您发布的代码中,我想我已经发现了问题所在。首先你这样做:

     var space = H5D.getSpace(dataset);
    

    那么你做

     var dataspace = H5D.getSpace(dataset);
    

    这两个调用做同样的事情,但是创建了两个不同的变量 你用space 调用H5S.selectHyperslab,但H5D.read 使用dataspace。 您需要确保始终使用正确的变量。如果您删除对H5D.getSpace 的第二次调用,并更改dataspace -&gt; space,它应该可以工作。

    【讨论】:

    • 谢谢。我可以在 C# 中使用它,但我无法仅针对该行正确获取数据。您能否编写附加代码如何将该块的数据检索到数组?
    • 您能否编辑您的问题以包含您已经在做的事情?
    • H5S.selectHyperslab(space, H5S.SelectOperator.SET, offset, count); var dims = H5S.getSimpleExtentDims(space); double[,] dataArray = new double[1, dims[1]]; // 只获取一个数组 var wrapArray = new H5Array(dataArray); H5D.read(dataset, dataType, wrapArray); // 看来我不能在 C# 命令中使用 stride 和 block
    • 我得到了这个错误 HDF5DotNet.dll 中发生了“System.AccessViolationException”类型的未处理异常附加信息:试图读取或写入受保护的内存。这通常表明其他内存已损坏。
    • 请问您可以将您的代码添加到您的原始问题中吗?它在 cmets 中的格式不正确,因此难以阅读。
    【解决方案2】:

    也许您想看看HDFql,因为它从 HDF5 的低级细节中抽象出来。在 C# 中使用 HDFql,您可以使用这样的 hyperslab 选择读取数据集 Values 的第 5 行和第 7 行:

    float [,]data = new float[2, 165702];
    
    HDFql.Execute("SELECT FROM Values(5:2:2:1) INTO MEMORY " + HDFql.VariableTransientRegister(data));
    

    之后,您可以通过变量data 访问这些行。示例:

    for(int x = 0; x < 2; x++)
    {
        for(int y = 0; y < 165702; y++)
        {
             System.Console.WriteLine(data[x, y]);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2023-03-24
      • 2016-01-02
      • 2016-02-10
      • 2017-06-26
      • 2012-03-26
      • 2018-03-25
      • 2014-05-18
      • 2023-04-08
      • 2016-11-17
      相关资源
      最近更新 更多