LCOV - code coverage report
Current view: top level - src/io - ReadHDF5Dataset.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 100 132 75.8 %
Date: 2020-12-16 07:07:30 Functions: 12 15 80.0 %
Branches: 69 202 34.2 %

           Branch data     Line data    Source code
       1                 :            : /** \file   ReadHDF5Dataset.cpp
       2                 :            :  *  \author Jason Kraftcheck
       3                 :            :  *  \date   2010-07-09
       4                 :            :  */
       5                 :            : 
       6                 :            : #include <assert.h>
       7                 :            : #include <string.h>
       8                 :            : #include <stdlib.h>
       9                 :            : #include <iostream>
      10                 :            : #include "moab/MOABConfig.h"
      11                 :            : #include "ReadHDF5Dataset.hpp"
      12                 :            : 
      13                 :            : #include "moab_mpe.h"
      14                 :            : 
      15                 :            : #include <H5Dpublic.h>
      16                 :            : #include <H5Tpublic.h>
      17                 :            : #include <H5Ppublic.h>
      18                 :            : #include <H5Spublic.h>
      19                 :            : #ifdef MOAB_HAVE_HDF5_PARALLEL
      20                 :            : #include <H5FDmpi.h>
      21                 :            : #include <H5FDmpio.h>
      22                 :            : #endif
      23                 :            : 
      24                 :            : #define HDF5_16API ( H5_VERS_MAJOR < 2 && H5_VERS_MINOR < 8 )
      25                 :            : 
      26                 :            : namespace moab
      27                 :            : {
      28                 :            : 
      29                 :            : // Selection of hyperslabs appears to be superlinear.  Don't try to select
      30                 :            : // more than a few thousand at a time or things start to get real slow.
      31                 :            : const size_t DEFAULT_HYPERSLAB_SELECTION_LIMIT  = 200;
      32                 :            : size_t ReadHDF5Dataset::hyperslabSelectionLimit = DEFAULT_HYPERSLAB_SELECTION_LIMIT;
      33                 :        132 : void ReadHDF5Dataset::default_hyperslab_selection_limit()
      34                 :            : {
      35                 :        132 :     hyperslabSelectionLimit = DEFAULT_HYPERSLAB_SELECTION_LIMIT;
      36                 :        132 : }
      37                 :            : 
      38                 :            : H5S_seloper_t ReadHDF5Dataset::hyperslabSelectOp = H5S_SELECT_OR;
      39                 :            : 
      40                 :            : #ifdef MOAB_HAVE_LIBMPE
      41                 :            : static std::pair< int, int > allocate_mpe_state( const char* name, const char* color )
      42                 :            : {
      43                 :            :     std::pair< int, int > result;
      44                 :            :     result.first  = MPE_Log_get_event_number();
      45                 :            :     result.second = MPE_Log_get_event_number();
      46                 :            :     MPE_Describe_state( result.first, result.second, name, color );
      47                 :            :     return result;
      48                 :            : }
      49                 :            : #else
      50                 :         42 : static std::pair< int, int > allocate_mpe_state( const char*, const char* )
      51                 :            : {
      52                 :         42 :     return std::pair< int, int >();
      53                 :            : }
      54                 :            : #endif
      55                 :            : 
      56                 :            : bool ReadHDF5Dataset::haveMPEEvents = false;
      57                 :            : std::pair< int, int > ReadHDF5Dataset::mpeReadEvent;
      58                 :            : std::pair< int, int > ReadHDF5Dataset::mpeReduceEvent;
      59                 :            : 
      60                 :          0 : ReadHDF5Dataset::ReadHDF5Dataset( const char* debug_desc, bool parallel, const Comm* communicator )
      61                 :            :     : closeDataSet( false ), dataSet( -1 ), dataSpace( -1 ), dataType( -1 ), fileType( -1 ), ioProp( H5P_DEFAULT ),
      62                 :            :       dataSpaceRank( 0 ), rowsInTable( 0 ), doConversion( false ), nativeParallel( parallel ), readCount( 0 ),
      63 [ #  # ][ #  # ]:          0 :       bufferSize( 0 ), mpiComm( communicator ), mpeDesc( debug_desc )
                 [ #  # ]
      64                 :            : {
      65         [ #  # ]:          0 :     if( !haveMPEEvents )
      66                 :            :     {
      67                 :          0 :         haveMPEEvents  = true;
      68         [ #  # ]:          0 :         mpeReadEvent   = allocate_mpe_state( "ReadHDF5Dataset::read", "yellow" );
      69         [ #  # ]:          0 :         mpeReduceEvent = allocate_mpe_state( "ReadHDF5Dataset::all_reduce", "yellow" );
      70                 :            :     }
      71                 :            : 
      72                 :            : #ifndef MOAB_HAVE_HDF5_PARALLEL
      73 [ #  # ][ #  # ]:          0 :     if( nativeParallel ) throw Exception( __LINE__ );
      74                 :            : #else
      75                 :            :     if( nativeParallel && !mpiComm ) throw Exception( __LINE__ );
      76                 :            : 
      77                 :            :     if( mpiComm )
      78                 :            :     {
      79                 :            :         ioProp = H5Pcreate( H5P_DATASET_XFER );
      80                 :            :         H5Pset_dxpl_mpio( ioProp, H5FD_MPIO_COLLECTIVE );
      81                 :            :     }
      82                 :            : #endif
      83                 :          0 : }
      84                 :            : 
      85                 :       1037 : ReadHDF5Dataset::ReadHDF5Dataset( const char* debug_desc, hid_t data_set_handle, bool parallel,
      86                 :            :                                   const Comm* communicator, bool close_data_set )
      87                 :            :     : closeDataSet( close_data_set ), dataSet( data_set_handle ), dataSpace( -1 ), dataType( -1 ), fileType( -1 ),
      88                 :            :       ioProp( H5P_DEFAULT ), dataSpaceRank( 0 ), rowsInTable( 0 ), doConversion( false ), nativeParallel( parallel ),
      89 [ +  - ][ +  - ]:       1037 :       readCount( 0 ), bufferSize( 0 ), mpiComm( communicator ), mpeDesc( debug_desc )
                 [ +  - ]
      90                 :            : {
      91         [ +  + ]:       1037 :     if( !haveMPEEvents )
      92                 :            :     {
      93                 :         21 :         haveMPEEvents  = true;
      94         [ +  - ]:         21 :         mpeReadEvent   = allocate_mpe_state( "ReadHDF5Dataset::read", "yellow" );
      95         [ +  - ]:         21 :         mpeReduceEvent = allocate_mpe_state( "ReadHDF5Dataset::all_reduce", "yellow" );
      96                 :            :     }
      97                 :            : 
      98         [ +  - ]:       1037 :     init( data_set_handle, close_data_set );
      99                 :            : 
     100                 :            : #ifndef MOAB_HAVE_HDF5_PARALLEL
     101 [ -  + ][ #  # ]:       1037 :     if( nativeParallel ) throw Exception( __LINE__ );
     102                 :            : #else
     103                 :            :     if( nativeParallel && !mpiComm ) throw Exception( __LINE__ );
     104                 :            : 
     105                 :            :     if( mpiComm )
     106                 :            :     {
     107                 :            :         ioProp = H5Pcreate( H5P_DATASET_XFER );
     108                 :            :         H5Pset_dxpl_mpio( ioProp, H5FD_MPIO_COLLECTIVE );
     109                 :            :     }
     110                 :            : #endif
     111                 :       1037 : }
     112                 :            : 
     113                 :       1037 : void ReadHDF5Dataset::init( hid_t data_set_handle, bool close_data_set )
     114                 :            : {
     115                 :       1037 :     closeDataSet = close_data_set;
     116                 :       1037 :     dataSet      = data_set_handle;
     117                 :            : 
     118                 :       1037 :     fileType = H5Dget_type( data_set_handle );
     119 [ -  + ][ #  # ]:       1037 :     if( fileType < 0 ) throw Exception( __LINE__ );
     120                 :            : 
     121                 :       1037 :     dataSpace = H5Dget_space( dataSet );
     122 [ -  + ][ #  # ]:       1037 :     if( dataSpace < 0 ) throw Exception( __LINE__ );
     123                 :            : 
     124                 :       1037 :     dataSpaceRank = H5Sget_simple_extent_dims( dataSpace, dataSetCount, dataSetOffset );
     125 [ -  + ][ #  # ]:       1037 :     if( dataSpaceRank < 0 ) throw Exception( __LINE__ );
     126                 :       1037 :     rowsInTable = dataSetCount[0];
     127                 :            : 
     128         [ +  + ]:       2244 :     for( int i = 0; i < dataSpaceRank; ++i )
     129                 :       1207 :         dataSetOffset[i] = 0;
     130                 :            : 
     131                 :       1037 :     currOffset = rangeEnd = internalRange.end();
     132                 :       1037 : }
     133                 :            : 
     134                 :         86 : unsigned ReadHDF5Dataset::columns() const
     135                 :            : {
     136         [ +  + ]:         86 :     if( dataSpaceRank == 1 )
     137                 :         69 :         return 1;
     138         [ +  - ]:         17 :     else if( dataSpaceRank == 2 )
     139                 :         17 :         return dataSetCount[1];
     140                 :            : 
     141         [ #  # ]:         86 :     throw Exception( __LINE__ );
     142                 :            : }
     143                 :            : 
     144                 :          0 : void ReadHDF5Dataset::set_column( unsigned column )
     145                 :            : {
     146 [ #  # ][ #  # ]:          0 :     if( dataSpaceRank != 2 || column >= dataSetCount[1] ) throw Exception( __LINE__ );
                 [ #  # ]
     147                 :          0 :     dataSetCount[1]  = 1;
     148                 :          0 :     dataSetOffset[1] = column;
     149                 :          0 : }
     150                 :            : 
     151                 :       1037 : Range::const_iterator ReadHDF5Dataset::next_end( Range::const_iterator iter )
     152                 :            : {
     153                 :       1037 :     size_t slabs_remaining = hyperslabSelectionLimit;
     154                 :       1037 :     size_t avail           = bufferSize;
     155 [ +  + ][ +  - ]:       2074 :     while( iter != rangeEnd && slabs_remaining )
                 [ +  + ]
     156                 :            :     {
     157 [ +  - ][ +  - ]:       1037 :         size_t count = *( iter.end_of_block() ) - *iter + 1;
     158         [ -  + ]:       1037 :         if( count >= avail )
     159                 :            :         {
     160                 :          0 :             iter += avail;
     161                 :          0 :             break;
     162                 :            :         }
     163                 :            : 
     164                 :       1037 :         avail -= count;
     165                 :       1037 :         iter += count;
     166                 :       1037 :         --slabs_remaining;
     167                 :            :     }
     168                 :       1037 :     return iter;
     169                 :            : }
     170                 :            : 
     171                 :       1037 : void ReadHDF5Dataset::set_file_ids( const Range& file_ids, EntityHandle start_id, hsize_t row_count, hid_t data_type )
     172                 :            : {
     173                 :       1037 :     startID    = start_id;
     174                 :       1037 :     currOffset = file_ids.begin();
     175                 :       1037 :     rangeEnd   = file_ids.end();
     176                 :       1037 :     readCount  = 0;
     177                 :       1037 :     bufferSize = row_count;
     178                 :            : 
     179                 :            :     // if a) user specified buffer size and b) we're doing a true
     180                 :            :     // parallel partial read and c) we're doing collective I/O, then
     181                 :            :     // we need to know the maximum number of reads that will be done.
     182                 :            : #ifdef MOAB_HAVE_HDF5_PARALLEL
     183                 :            :     if( nativeParallel )
     184                 :            :     {
     185                 :            :         Range::const_iterator iter = currOffset;
     186                 :            :         while( iter != rangeEnd )
     187                 :            :         {
     188                 :            :             ++readCount;
     189                 :            :             iter = next_end( iter );
     190                 :            :         }
     191                 :            : 
     192                 :            :         MPE_Log_event( mpeReduceEvent.first, (int)readCount, mpeDesc.c_str() );
     193                 :            :         unsigned long recv = readCount, send = readCount;
     194                 :            :         MPI_Allreduce( &send, &recv, 1, MPI_UNSIGNED_LONG, MPI_MAX, *mpiComm );
     195                 :            :         readCount = recv;
     196                 :            :         MPE_Log_event( mpeReduceEvent.second, (int)readCount, mpeDesc.c_str() );
     197                 :            :     }
     198                 :            : #endif
     199                 :            : 
     200                 :       1037 :     dataType     = data_type;
     201                 :       1037 :     htri_t equal = H5Tequal( fileType, dataType );
     202 [ -  + ][ #  # ]:       1037 :     if( equal < 0 ) throw Exception( __LINE__ );
     203                 :       1037 :     doConversion = !equal;
     204                 :            : 
     205                 :            :     // We always read in the format of the file to avoid stupind HDF5
     206                 :            :     // library behavior when reading in parallel.  We call H5Tconvert
     207                 :            :     // ourselves to do the data conversion.  If the type we're reading
     208                 :            :     // from the file is larger than the type we want in memory, then
     209                 :            :     // we need to reduce num_rows so that we can read the larger type
     210                 :            :     // from the file into the passed buffer mean to accomodate num_rows
     211                 :            :     // of values of the smaller in-memory type.
     212         [ +  + ]:       1037 :     if( doConversion )
     213                 :            :     {
     214                 :            :         size_t mem_size, file_size;
     215                 :         86 :         mem_size  = H5Tget_size( dataType );
     216                 :         86 :         file_size = H5Tget_size( fileType );
     217         [ -  + ]:         86 :         if( file_size > mem_size ) bufferSize = bufferSize * mem_size / file_size;
     218                 :            :     }
     219                 :       1037 : }
     220                 :            : 
     221                 :        235 : void ReadHDF5Dataset::set_all_file_ids( hsize_t row_count, hid_t data_type )
     222                 :            : {
     223                 :        235 :     internalRange.clear();
     224                 :        235 :     internalRange.insert( (EntityHandle)1, ( EntityHandle )( rowsInTable ) );
     225                 :        235 :     set_file_ids( internalRange, 1, row_count, data_type );
     226                 :        235 : }
     227                 :            : 
     228                 :       2074 : ReadHDF5Dataset::~ReadHDF5Dataset()
     229                 :            : {
     230         [ +  - ]:       1037 :     if( fileType >= 0 ) H5Tclose( fileType );
     231         [ +  - ]:       1037 :     if( dataSpace >= 0 ) H5Sclose( dataSpace );
     232 [ +  + ][ +  - ]:       1037 :     if( closeDataSet && dataSet >= 0 ) H5Dclose( dataSet );
     233                 :       1037 :     dataSpace = dataSet = -1;
     234         [ -  + ]:       1037 :     if( ioProp != H5P_DEFAULT ) H5Pclose( ioProp );
     235                 :       1037 : }
     236                 :            : 
     237                 :       1037 : void ReadHDF5Dataset::read( void* buffer, size_t& rows_read )
     238                 :            : {
     239                 :            :     herr_t err;
     240                 :       1037 :     rows_read = 0;
     241                 :            : 
     242 [ +  - ][ +  - ]:       1037 :     MPE_Log_event( mpeReadEvent.first, (int)readCount, mpeDesc.c_str() );
                 [ +  - ]
     243         [ +  - ]:       1037 :     if( currOffset != rangeEnd )
     244                 :            :     {
     245                 :            : 
     246                 :            :         // Build H5S hyperslab selection describing the portions of the
     247                 :            :         // data set to read
     248                 :       1037 :         H5S_seloper_t sop       = H5S_SELECT_SET;
     249         [ +  - ]:       1037 :         Range::iterator new_end = next_end( currOffset );
     250 [ +  - ][ +  + ]:       2074 :         while( currOffset != new_end )
     251                 :            :         {
     252 [ +  - ][ +  - ]:       1037 :             size_t count = *( currOffset.end_of_block() ) - *currOffset + 1;
                 [ +  - ]
     253 [ +  - ][ -  + ]:       1037 :             if( new_end != rangeEnd && *currOffset + count > *new_end ) { count = *new_end - *currOffset; }
         [ #  # ][ #  # ]
         [ #  # ][ -  + ]
         [ #  # ][ #  # ]
     254                 :       1037 :             rows_read += count;
     255                 :            : 
     256         [ +  - ]:       1037 :             dataSetOffset[0] = *currOffset - startID;
     257                 :       1037 :             dataSetCount[0]  = count;
     258         [ +  - ]:       1037 :             err              = H5Sselect_hyperslab( dataSpace, sop, dataSetOffset, NULL, dataSetCount, 0 );
     259 [ -  + ][ #  # ]:       1037 :             if( err < 0 ) throw Exception( __LINE__ );
     260                 :       1037 :             sop = hyperslabSelectOp;  // subsequent calls to select_hyperslab append
     261                 :            : 
     262         [ +  - ]:       1037 :             currOffset += count;
     263                 :            :         }
     264                 :            : 
     265                 :            :         // Create a data space describing the memory in which to read the data
     266                 :       1037 :         dataSetCount[0] = rows_read;
     267         [ +  - ]:       1037 :         hid_t mem_id    = H5Screate_simple( dataSpaceRank, dataSetCount, NULL );
     268 [ -  + ][ #  # ]:       1037 :         if( mem_id < 0 ) throw Exception( __LINE__ );
     269                 :            : 
     270                 :            :         // Do the actual read
     271         [ +  - ]:       1037 :         err = H5Dread( dataSet, fileType, mem_id, dataSpace, ioProp, buffer );
     272         [ +  - ]:       1037 :         H5Sclose( mem_id );
     273 [ -  + ][ #  # ]:       1037 :         if( err < 0 ) throw Exception( __LINE__ );
     274                 :            : 
     275         [ -  + ]:       1037 :         if( readCount ) --readCount;
     276                 :            : 
     277         [ +  + ]:       1037 :         if( doConversion )
     278                 :            :         {
     279 [ +  - ][ +  - ]:         86 :             err = H5Tconvert( fileType, dataType, rows_read * columns(), buffer, 0, H5P_DEFAULT );
     280 [ -  + ][ #  # ]:       1037 :             if( err < 0 ) throw Exception( __LINE__ );
     281                 :            :         }
     282                 :            :     }
     283         [ #  # ]:          0 :     else if( readCount )
     284                 :            :     {
     285                 :          0 :         null_read();
     286                 :          0 :         --readCount;
     287                 :            :     }
     288 [ +  - ][ +  - ]:       1037 :     MPE_Log_event( mpeReadEvent.second, (int)readCount, mpeDesc.c_str() );
                 [ +  - ]
     289                 :       1037 : }
     290                 :            : 
     291                 :          0 : void ReadHDF5Dataset::null_read()
     292                 :            : {
     293                 :            :     herr_t err;
     294         [ #  # ]:          0 :     err = H5Sselect_none( dataSpace );
     295 [ #  # ][ #  # ]:          0 :     if( err < 0 ) throw Exception( __LINE__ );
     296                 :            : 
     297                 :            :     //#if HDF5_16API
     298                 :          0 :     hsize_t one  = 1;
     299         [ #  # ]:          0 :     hid_t mem_id = H5Screate_simple( 1, &one, NULL );
     300 [ #  # ][ #  # ]:          0 :     if( mem_id < 0 ) throw Exception( __LINE__ );
     301         [ #  # ]:          0 :     err = H5Sselect_none( mem_id );
     302         [ #  # ]:          0 :     if( err < 0 )
     303                 :            :     {
     304         [ #  # ]:          0 :         H5Sclose( mem_id );
     305         [ #  # ]:          0 :         throw Exception( __LINE__ );
     306                 :            :     }
     307                 :            :     //#else
     308                 :            :     //  hid_t mem_id = H5Screate(H5S_NULL);
     309                 :            :     //  if (mem_id < 0)
     310                 :            :     //    throw Exception(__LINE__);
     311                 :            :     //#endif
     312                 :            : 
     313         [ #  # ]:          0 :     err = H5Dread( dataSet, fileType, mem_id, dataSpace, ioProp, 0 );
     314         [ #  # ]:          0 :     H5Sclose( mem_id );
     315 [ #  # ][ #  # ]:          0 :     if( err < 0 ) throw Exception( __LINE__ );
     316                 :          0 : }
     317                 :            : 
     318 [ +  - ][ +  - ]:        228 : }  // namespace moab

Generated by: LCOV version 1.11