2013-02-28 18 views
5

Raccolgo solo HDF5 e sono un po 'confuso circa la differenza tra la creazione di dati per la memoria e la creazione di dati per il file. Qual è la differenza?Tipo di composto HDF5 Nativo rispetto a IEEE

In this esempio, la creazione di un tipo di dati composto richiede i dati da creare nella memoria e messi nel file:

/* 
* Create the memory data type. 
*/ 
s1_tid = H5Tcreate (H5T_COMPOUND, sizeof(s1_t)); 
H5Tinsert(s1_tid, "a_name", HOFFSET(s1_t, a), H5T_NATIVE_INT); 
H5Tinsert(s1_tid, "c_name", HOFFSET(s1_t, c), H5T_NATIVE_DOUBLE); 
H5Tinsert(s1_tid, "b_name", HOFFSET(s1_t, b), H5T_NATIVE_FLOAT); 

/* 
* Create the dataset. 
*/ 
dataset = H5Dcreate(file, DATASETNAME, s1_tid, space, H5P_DEFAULT); 

/* 
* Wtite data to the dataset; 
*/ 
status = H5Dwrite(dataset, s1_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, s1); 

Tuttavia, in un altro esempio here, l'autore crea anche un dato composti per la file, che specifica un diverso tipo di dati. Ad esempio, nella creazione del tipo di dati per la memoria, serial_no utilizzato tipo H5T_NATIVE_INT, ma nella creazione del tipo di dati per il file, serial_no utilizzato H5T_STD_I64BE. Perché lo fa?

/* 
* Create the compound datatype for memory. 
*/ 
memtype = H5Tcreate (H5T_COMPOUND, sizeof (sensor_t)); 
status = H5Tinsert (memtype, "Serial number", 
      HOFFSET (sensor_t, serial_no), H5T_NATIVE_INT); 
status = H5Tinsert (memtype, "Location", HOFFSET (sensor_t, location), 
      strtype); 
status = H5Tinsert (memtype, "Temperature (F)", 
      HOFFSET (sensor_t, temperature), H5T_NATIVE_DOUBLE); 
status = H5Tinsert (memtype, "Pressure (inHg)", 
      HOFFSET (sensor_t, pressure), H5T_NATIVE_DOUBLE); 

/* 
* Create the compound datatype for the file. Because the standard 
* types we are using for the file may have different sizes than 
* the corresponding native types, we must manually calculate the 
* offset of each member. 
*/ 
filetype = H5Tcreate (H5T_COMPOUND, 8 + sizeof (hvl_t) + 8 + 8); 
status = H5Tinsert (filetype, "Serial number", 0, H5T_STD_I64BE); 
status = H5Tinsert (filetype, "Location", 8, strtype); 
status = H5Tinsert (filetype, "Temperature (F)", 8 + sizeof (hvl_t), 
      H5T_IEEE_F64BE); 
status = H5Tinsert (filetype, "Pressure (inHg)", 8 + sizeof (hvl_t) + 8, 
      H5T_IEEE_F64BE); 

/* 
* Create dataspace. Setting maximum size to NULL sets the maximum 
* size to be the current size. 
*/ 
space = H5Screate_simple (1, dims, NULL); 

/* 
* Create the dataset and write the compound data to it. 
*/ 
dset = H5Dcreate (file, DATASET, filetype, space, H5P_DEFAULT, H5P_DEFAULT, 
      H5P_DEFAULT); 
status = H5Dwrite (dset, memtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, wdata); 

Qual è la differenza tra questi due metodi?

risposta

5

Da http://www.hdfgroup.org/HDF5/doc/UG/UG_frame11Datatypes.html:

H5T_NATIVE_INT corrisponde ad un tipo C int. Su un PC basato su Intel, questo tipo è lo stesso di H5T_STD_I32LE, mentre su un sistema MIPS sarebbe equivalente a H5T_STD_I32BE.

Vale a dire, H5T_NATIVE_INT ha un diverso layout di memoria su diversi tipi di processori. Se i tuoi dati vengono utilizzati solo in memoria, il che significa che i tuoi dati non usciranno da questa macchina, potresti voler utilizzare H5T_NATIVE_INT per prestazioni migliori.

Tuttavia, se i dati verranno salvati in un file e saranno utilizzati da sistemi diversi, è necessario specificare un determinato tipo int per mantenere i dati correttamente leggibili, ad es. H5T_STD_I64BE o H5T_STD_I32LE. Se utilizzi H5T_NATIVE_INT e hai creato un file di dati su PC basato su Intel, il numero verrà salvato come H5T_STD_I32LE. Quando questo file viene utilizzato da un sistema MIPS, leggerà il numero come H5T_STD_I32BE, che non è previsto.

+0

ringraziamento tu, questo era molto chiaro – foboi1122

+0

dalla mia interpretazione: è ok avere un tipo di file con NATIVE_some_type; è responsabilità dei clienti eseguire la mappatura durante la lettura del contenuto. in altre parole: "Quando questo file viene utilizzato da un sistema MIPS, leggerà il numero come H5T_STD_I32BE, che non è previsto." non è vero; il client dovrebbe leggere il tipo di file e creare di conseguenza il layout di memoria. Il client dovrebbe aspettarsi la mancata corrispondenza dell'ordine dei byte e attenuarlo con la mappatura corretta. L'esempio dimostra che l'ordine/layout dei byte del file è disaccoppiato dall'ordine/layout del byte host (memoria). –

+0

@StevenVarga Se si usa H5T_NATIVE_INT, non si sa che è big endian o little endian, a meno che non si metta un flag da qualche parte per dire quale sia l'ordine dei byte. Anche se conosci l'effettivo ordine dei byte, non è uno sforzo banale convertire tutti i dati dopo che sono stati caricati. Anche la manutenzione del codice è difficile. Perché preoccuparsi? Perché non utilizzare l'ordine dei byte esplicito quando si salva in un file? – Chen

0

L'altra risposta qui manca alcune idee chiave e rende l'utilizzo dei tipi di dati HDF5 più difficile di quello che è.

Per cominciare, i tipi NATIVE sono semplicemente alias per ciò su cui i tipi C si connettono su quella piattaforma (questo viene rilevato quando la libreria HDF5 è costruita). Se li usi nel tuo codice e guardi il file che hai creato con lo strumento h5dump, non vedrai il tipo di dati NATIVE ma vedrai invece il tipo di dati reale (H5T_STD_I32LE o whatnot). Questi tipi di NATIVE sono certamente un po 'confusi, ma sono utili per il mapping tra tipi C e tipi di dati HDF5 senza dover conoscere l'ordine dei byte del sistema in cui ci si trova.

L'altro equivoco che voglio chiarire è che la libreria convertirà i tipi per te quando è ragionevole farlo. Se un set di dati contiene valori H5T_STD_I32BE e dichiari che il buffer I/O è di H5T_NATIVE_INT su un sistema little-endian, la libreria HDF5 convertirà gli interi del set di dati big-endian in interi little-endian in memoria per te. Non dovrebbe essere necessario eseguire lo scambio dei byte da solo.

Ecco un modo semplice per pensarci:

  • si dichiara stoccaggio tipo di dati di un set di dati quando si chiama H5Dcreate().
  • Si dichiara il tipo di dati del buffer I/O quando si chiama H5Dread() e H5Dwrite().

Ancora, se queste differenze e le conversioni di tipo sono ragionevoli, i dati verranno convertiti durante le chiamate di lettura/scrittura.

Si noti che questa conversione di tipo potrebbe avere implicazioni sulle prestazioni in applicazioni time-critical. Se le piattaforme in cui i dati saranno scritti e letti differiscono in ordine di byte o dimensione della parola, potresti voler impostare in modo esplicito il tipo di dati invece di utilizzare gli alias NATIVE in modo da poter forzare la conversione a prendere posto sulla piattaforma meno importante.

Esempio: Supponiamo di disporre di un writer BE e di un lettore LE e che i dati arrivino lentamente, ma le letture devono essere il più veloci possibile. in questo caso, vorrai creare in modo esplicito il set di dati per memorizzare i dati H5T_STD_I32LE in modo che le conversioni dei tipi di dati avvengano sul writer.

Un'ultima cosa: è meglio usare la macro HOFFSET (s, m) invece di calcolare gli offset manualmente durante la costruzione di tipi composti. È più gestibile e il tuo codice sembrerà più bello.

Se volete maggiori informazioni su tipi di dati HDF5, controllare il capitolo 6 della guida per l'utente qui: https://support.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html

È anche possibile controllare la documentazione H5T API nel manuale di riferimento qui: https://support.hdfgroup.org/HDF5/doc/RM/RM_H5Front.html