HDF5 rowmajor或colmajor

时间:2014-06-09 08:50:37

标签: hdf5

是否可以知道以HDF5格式存储的矩阵是在RowMajor还是ColMajor?例如,当我从octave中保存矩阵时,它将它们内部存储为ColMajor,当我在C代码中读取它们时,我需要转置它们,其中矩阵存储在RowMajor中,反之亦然。

2 个答案:

答案 0 :(得分:5)

HDF5按行主要顺序存储数据:

  

HDF5使用C存储约定,假设最后列出的维度是变化最快的维度,并且首先列出的维度是最慢的维度。

来自HDF5 User's Guide

然而,如果您使用Octave的内置HDF5界面,它会自动为您调换阵列。一般来说,如何在HDF5文件中实际写入数据应该对最终用户完全不透明,并且接口应该处理数组排序等方面的差异。

答案 1 :(得分:4)

正如@Yossarian指出的那样。 HDF5始终将数据存储为行主要(C约定)。 Octave与Fortran相同,内部存储数据为专栏。

当从Octave编写矩阵时,HDF5层会为您进行转置,因此无论您使用何种语言,它都会被写为行专业。这提供了文件的可移植性。

正如@Yossarian所提到的,HDF5用户指南第7.3.2.5节中有一个很好的例子。以下是使用Octave再现的例子(<差不多):

octave:1> A = [ 1:3; 4:6 ]
A =

   1   2   3
   4   5   6

octave:2> save("-hdf5", "test.h5", "A")
octave:3> quit

~$ h5dump test.h5
HDF5 "test.h5" {
GROUP "/" {
   COMMENT "# Created by Octave 3.6.4, Fri Jun 13 08:36:16 2014 MDT <user@localhost>"
   GROUP "A" {
      ATTRIBUTE "OCTAVE_NEW_FORMAT" {
         DATATYPE  H5T_STD_U8LE
         DATASPACE  SCALAR
         DATA {
         (0): 1
         }
      }
      DATASET "type" {
         DATATYPE  H5T_STRING {
            STRSIZE 7;
            STRPAD H5T_STR_NULLTERM;
            CSET H5T_CSET_ASCII;
            CTYPE H5T_C_S1;
         }
         DATASPACE  SCALAR
         DATA {
         (0): "matrix"
         }
      }
      DATASET "value" {
         DATATYPE  H5T_IEEE_F64LE
         DATASPACE  SIMPLE { ( 3, 2 ) / ( 3, 2 ) }
         DATA {
         (0,0): 1, 4,
         (1,0): 2, 5,
         (2,0): 3, 6
         }
      }
   }
}
}

注意HDF5层如何转换矩阵以确保它以行主格式存储。

然后用C:

读取它的一个例子
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <hdf5.h>

#define FILE "test.h5"
#define DS   "A/value"

int
main(int argc, char **argv)
{
        int i = 0;
        int j = 0;
        int n = 0;
        int x = 0;
        int rank = 0;
        hid_t file_id;
        hid_t space_id;
        hid_t dset_id;
        herr_t stat;
        hsize_t *dims = NULL;
        int *data = NULL;

        file_id  = H5Fopen(FILE, H5F_ACC_RDONLY, H5P_DEFAULT);
        dset_id  = H5Dopen(file_id, DS, dset_id);

        space_id = H5Dget_space(dset_id);
        n    = H5Sget_simple_extent_npoints(space_id);
        rank = H5Sget_simple_extent_ndims(space_id);

        dims = malloc(rank*sizeof(int));
        stat = H5Sget_simple_extent_dims(space_id, dims, NULL);

        printf("rank: %d\t dimensions: ", rank);
        for (i = 0; i < rank; ++i) {
                if (i == 0) {
                        printf("(");
                }
                printf("%llu", dims[i]);
                if (i == (rank -1)) {
                        printf(")\n");
                } else {
                        printf(" x ");
                }
        }
        data = malloc(n*sizeof(int));
        memset(data, 0, n*sizeof(int));
        stat  = H5Dread(dset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT,
                         data);


        printf("%s:\n", DS);
        for (i = 0; i < dims[0]; ++i) {
                printf(" [ ");
                for (j = 0; j < dims[1]; ++j) {
                        x = i * dims[1] + j;
                        printf("%d ", data[x]);
                }
                printf("]\n");
        }

        stat  = H5Sclose(space_id);
        stat  = H5Dclose(dset_id);
        stat  = H5Fclose(file_id);


        return(EXIT_SUCCESS);
}

编译并运行时给出:

~$ h5cc -o rmat rmat.c
~$ ./rmat
rank: 2  dimensions: (3 x 2)
A/value:
 [ 1 4 ]
 [ 2 5 ]
 [ 3 6 ]

这很好,因为它意味着矩阵在内存中优化存储。它的意思是,你必须改变你的计算方式。对于行主要,您需要进行预乘,而对于列主要,您应该进行后乘。 这是一个example,希望它解释得更清楚。

这有帮助吗?