2014-06-09 14 views
5

E 'possibile sapere se una matrice memorizzata in formato HDF5 è in RowMajor o ColMajor? Ad esempio, quando salvo le matrici da ottava, che le memorizzano internamente come ColMajor, devo trasporle quando le leggo nel mio codice C in cui le matrici sono memorizzate in RowMajor e viceversa.HDF5 rowmajor o colmajor

risposta

4

HDF5 memorizza i dati in fila fine importante:

HDF5 utilizza convenzioni di stoccaggio C, assumendo che l'ultima dimensione elencato è la dimensione più rapida evoluzione e la prima quotata dimensione è il cambiamento più lento.

dal HDF5 User's Guide.

Tuttavia, se si sta utilizzando interfaccia incorporata HDF5, si trasporre automaticamente gli array di Octave per voi. In generale, il modo in cui i dati vengono effettivamente scritti nel file HDF5 deve essere completamente opaco per l'utente finale e l'interfaccia deve gestire le differenze nell'ordinamento degli array, ecc.

+0

Così, quando ho letto i dati esportati da un'ottava e loro sono trasposti E 'dovuto al fatto che Octave non ha seguito le convenzioni HDF5, giusto? – remi

+0

Cosa stai leggendo? – Yossarian

+0

Sto usando un codice in C++ scritto da me stesso. Ho appena letto le dimensioni del set di dati, quindi ho letto i valori. – remi

4

Come sottolineato da @ Yossarian. HDF5 memorizza sempre i dati come riga maggiore (convenzione C). Octave è uguale a Fortran e memorizza internamente i dati come colonna principale.

Quando si scrive una matrice da Octave, lo strato HDF5 fa la trasposta per voi, quindi è sempre scritto come row-major, non importa quale lingua si usa. Ciò fornisce la portabilità del file.

C'è un ottimo esempio nel utente HDF5 sezione Guida 7.3.2.5, come detto da @Yossarian. Ecco l'esempio (quasi) riprodotto utilizzando 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 <[email protected]>" 
    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 
     } 
     } 
    } 
} 
} 

Notate come lo strato HDF5 ha recepito la matrice per assicurarsi che vengono memorizzati in formato row-major.

Poi un esempio di lettura in 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); 
} 

Quando compilato ed eseguito dà:

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

Questo è grande quanto significa le matrici sono memorizzati nella memoria ottimizzati. Ciò che significa però è che devi cambiare il modo in cui fai i tuoi calcoli. Per row-major è necessario fare una pre-moltiplicazione, mentre per la colonna-major si dovrebbe fare post-moltiplicazione. Ecco un example, si spera che venga spiegato un po 'più chiaro.

fa questo aiuto?

+0

Thx per l'esempio molto dettagliato.Ma sulla base del tuo esempio, HDF5 non memorizza la matrice in RowMajor: la matrice 'A', in Octave memory, in ColMajor, apparirebbe come un vettore 1D contenente i valori' {1,4,2,5,3,6 } '. Inoltre, dim [0] = 2 e dim1 [1] = 3. Quando si legge A nel prog di C, la matrice di lettura ha dimensioni miste e il RowMajor, equivalente di memoria 1D della matrice A letto, è anche {1,4,2,5,3,6}. Mi sarei aspettato '{1,2,3,4,5,6}'. Almeno, mi aspetterei qualche suggerimento nel file HDF5 per sapere se il layout di memoria per il coeff della matrice durante la scrittura era riga o col maggiore per leggerlo bene. – remi