Commit ad01b6e3 authored by Tomáš Oberhuber's avatar Tomáš Oberhuber Committed by Tomáš Oberhuber
Browse files

Added type conversion to File read and write.

parent 4b22c5e5
Loading
Loading
Loading
Loading
+101 −44
Original line number Diff line number Diff line
@@ -88,7 +88,7 @@ bool File::read( Type* buffer, std::streamsize elements )
   if( ! elements )
      return true;

   return read_impl< Type, Device >( buffer, elements );
   return read_impl< Type, Device, SourceType >( buffer, elements );
}

// Host
@@ -150,7 +150,7 @@ bool File::read_impl( Type* buffer, std::streamsize elements )
   else
   {
      const std::streamsize cast_buffer_size = std::min( TransferBufferSize / (std::streamsize) sizeof(SourceType), elements );
      using BaseType = typename std::remove_cv< SorceType >::type;
      using BaseType = typename std::remove_cv< SourceType >::type;
      std::unique_ptr< BaseType[] > cast_buffer{ new BaseType[ cast_buffer_size ] };

      while( readElements < elements )
@@ -186,6 +186,8 @@ bool File::read_impl( Type* buffer, std::streamsize elements )
   std::unique_ptr< BaseType[] > host_buffer{ new BaseType[ host_buffer_size ] };

   std::streamsize readElements = 0;
   if( std::is_same< Type, SourceType >::value )
   {
      while( readElements < elements )
      {
         const std::streamsize transfer = std::min( elements - readElements, host_buffer_size );
@@ -205,13 +207,19 @@ bool File::read_impl( Type* buffer, std::streamsize elements )
         readElements += transfer;
      }
      free( host_buffer );
   }
   else
   {
      std::cerr << "Type conversion during loading is not implemented for MIC." << std::endl;
      abort();
   }
   return true;
#else
   throw Exceptions::MICSupportMissing();
#endif
}

template< class Type, typename Device, typename TargeType >
template< class Type, typename Device, typename TargetType >
bool File::write( const Type* buffer, std::streamsize elements )
{
   TNL_ASSERT_GE( elements, 0, "Number of elements to write must be non-negative." );
@@ -219,7 +227,7 @@ bool File::write( const Type* buffer, std::streamsize elements )
   if( ! elements )
      return true;

   return write_impl< Type, Device >( buffer, elements );
   return write_impl< Type, Device, TargetType >( buffer, elements );
}

// Host
@@ -229,7 +237,24 @@ template< typename Type,
          typename >
bool File::write_impl( const Type* buffer, std::streamsize elements )
{
   if( std::is_same< Type, TargetType >::value )
      file.write( reinterpret_cast<const char*>(buffer), sizeof(Type) * elements );
   else
   {
      const std::streamsize cast_buffer_size = std::min( TransferBufferSize / (std::streamsize) sizeof(TargetType), elements );
      using BaseType = typename std::remove_cv< TargetType >::type;
      std::unique_ptr< BaseType[] > cast_buffer{ new BaseType[ cast_buffer_size ] };
      std::streamsize writtenElements = 0;
      while( writtenElements < elements )
      {
         const std::streamsize transfer = std::min( elements - writtenElements, cast_buffer_size );
         for( std::streamsize i = 0; i < transfer; i++ )
            cast_buffer[ i ] = static_cast< TargetType >( buffer[ writtenElements ++ ] );
         file.write( reinterpret_cast<char*>(cast_buffer.get()), sizeof(TargetType) * transfer );
         writtenElements += transfer;
      }

   }
   return true;
}

@@ -246,6 +271,8 @@ bool File::write_impl( const Type* buffer, std::streamsize elements )
   std::unique_ptr< BaseType[] > host_buffer{ new BaseType[ host_buffer_size ] };

   std::streamsize writtenElements = 0;
   if( std::is_same< Type, TargetType >::value )
   {
      while( writtenElements < elements )
      {
         const std::streamsize transfer = std::min( elements - writtenElements, host_buffer_size );
@@ -257,6 +284,28 @@ bool File::write_impl( const Type* buffer, std::streamsize elements )
         file.write( reinterpret_cast<const char*>(host_buffer.get()), sizeof(Type) * transfer );
         writtenElements += transfer;
      }
   }
   else
   {
      const std::streamsize cast_buffer_size = std::min( TransferBufferSize / (std::streamsize) sizeof(TargetType), elements );
      using BaseType = typename std::remove_cv< TargetType >::type;
      std::unique_ptr< BaseType[] > cast_buffer{ new BaseType[ cast_buffer_size ] };

      while( writtenElements < elements )
      {
         const std::streamsize transfer = std::min( elements - writtenElements, host_buffer_size );
         cudaMemcpy( (void*) host_buffer.get(),
                     (void*) &buffer[ writtenElements ],
                     transfer * sizeof(Type),
                     cudaMemcpyDeviceToHost );
         TNL_CHECK_CUDA_DEVICE;
         for( std::streamsize i = 0; i < transfer; i++ )
            cast_buffer[ i ] = static_cast< TargetType >( host_buffer[ i ] );

         file.write( reinterpret_cast<const char*>(cast_buffer.get()), sizeof(TargetType) * transfer );
         writtenElements += transfer;
      }
   }
   return true;
#else
   throw Exceptions::CudaSupportMissing();
@@ -276,6 +325,8 @@ bool File::write_impl( const Type* buffer, std::streamsize elements )
   std::unique_ptr< BaseType[] > host_buffer{ new BaseType[ host_buffer_size ] };

   std::streamsize writtenElements = 0;
   if( std::is_same< Type, TargetType >::value )
   {
      while( this->writtenElements < elements )
      {
         const std::streamsize transfer = std::min( elements - writtenElements, host_buffer_size );
@@ -295,6 +346,12 @@ bool File::write_impl( const Type* buffer, std::streamsize elements )
         file.write( reinterpret_cast<const char*>(host_buffer.get()), sizeof(Type) * transfer );
         writtenElements += transfer;
      }
   }
   else
   {
      std::cerr << "Type conversion during saving is not implemented for MIC." << std::endl;
      abort();
   }
   return true;
#else
   throw Exceptions::MICSupportMissing();
+85 −0
Original line number Diff line number Diff line
@@ -50,6 +50,37 @@ TEST( FileTest, WriteAndRead )
   EXPECT_EQ( std::remove( "test-file.tnl" ), 0 );
};

TEST( FileTest, WriteAndReadWithConversion )
{
   double doubleData[ 3 ] = {  3.1415926535897932384626433,
                               2.7182818284590452353602874,
                               1.6180339887498948482045868 };
   float floatData[ 3 ];
   int intData[ 3 ];
   File file;
   file.open( "test-file.tnl", File::Mode::Out | File::Mode::Truncate );
   file.write< double, Devices::Host, float >( doubleData, 3 );
   file.close();

   file.open( "test-file.tnl", File::Mode::In );
   file.read< float, Devices::Host, float >( floatData, 3 );
   file.close();

   file.open( "test-file.tnl", File::Mode::In );
   file.read< int, Devices::Host, float >( intData, 3 );
   file.close();

   EXPECT_NEAR( floatData[ 0 ], 3.14159, 0.0001 );
   EXPECT_NEAR( floatData[ 1 ], 2.71828, 0.0001 );
   EXPECT_NEAR( floatData[ 2 ], 1.61803, 0.0001 );

   EXPECT_EQ( intData[ 0 ], 3 );
   EXPECT_EQ( intData[ 1 ], 2 );
   EXPECT_EQ( intData[ 2 ], 1 );

   EXPECT_EQ( std::remove( "test-file.tnl" ), 0 );
}

#ifdef HAVE_CUDA
TEST( FileTest, WriteAndReadCUDA )
{
@@ -123,6 +154,60 @@ TEST( FileTest, WriteAndReadCUDA )

   EXPECT_EQ( std::remove( "test-file.tnl" ), 0 );
};

TEST( FileTest, WriteAndReadCUDAWithConversion )
{
   const double constDoubleData[ 3 ] = {  3.1415926535897932384626433,
                                          2.7182818284590452353602874,
                                          1.6180339887498948482045868 };
   float floatData[ 3 ];
   int intData[ 3 ];

   int* cudaIntData;
   float* cudaFloatData;
   const double* cudaConstDoubleData;
   cudaMalloc( ( void** ) &cudaIntData, 3 * sizeof( int ) );
   cudaMalloc( ( void** ) &cudaFloatData, 3 * sizeof( float ) );
   cudaMalloc( ( void** ) &cudaConstDoubleData, 3 * sizeof( double ) );
   cudaMemcpy( (void*) cudaConstDoubleData,
               &constDoubleData,
               3 * sizeof( double ),
               cudaMemcpyHostToDevice );

   File file;
   file.open( String( "cuda-test-file.tnl" ), File::Mode::Out | File::Mode::Truncate );
   file.write< double, Devices::Cuda, float >( cudaConstDoubleData, 3 );
   file.close();

   file.open( String( "cuda-test-file.tnl" ), File::Mode::In );
   file.read< float, Devices::Cuda, float >( cudaFloatData, 3 );
   file.close();

   file.open( String( "cuda-test-file.tnl" ), File::Mode::In );
   file.read< int, Devices::Cuda, float >( cudaIntData, 3 );
   file.close();

   cudaMemcpy( floatData,
               cudaFloatData,
               3 * sizeof( float ),
               cudaMemcpyDeviceToHost );
   cudaMemcpy( &intData,
               cudaIntData,
               3* sizeof( int ),
               cudaMemcpyDeviceToHost );


   EXPECT_NEAR( floatData[ 0 ], 3.14159, 0.0001 );
   EXPECT_NEAR( floatData[ 1 ], 2.71828, 0.0001 );
   EXPECT_NEAR( floatData[ 2 ], 1.61803, 0.0001 );

   EXPECT_EQ( intData[ 0 ], 3 );
   EXPECT_EQ( intData[ 1 ], 2 );
   EXPECT_EQ( intData[ 2 ], 1 );

   EXPECT_EQ( std::remove( "cuda-test-file.tnl" ), 0 );
};

#endif
#endif