Commit 49c4ec9d authored by Jakub Klinkovský's avatar Jakub Klinkovský
Browse files

Refactoring TNL::File

parent 20aca669
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -44,13 +44,13 @@ bool File :: open( const String& fileName,
         std::cout << " for writing ... " << std::endl;
   }
   if( mode == IOMode::read )
      file = fopen( fileName. getString(), "r" );
      file = std::fopen( fileName.getString(), "r" );
   if( mode == IOMode::write )
      file = fopen( fileName. getString(), "w" );
      file = std::fopen( fileName.getString(), "w" );
   if( file ==  NULL )
   {
      std::cerr << "I am not able to open the file " << fileName << ". ";
      perror( "" );
      std::perror( "" );
      return false;
   }
   this->fileOK = true;
@@ -63,7 +63,7 @@ bool File :: close()
   if( verbose )
      std::cout << "Closing the file " << getFileName() << " ... " << std::endl;

   if( fclose( file ) != 0 )
   if( std::fclose( file ) != 0 )
   {
      std::cerr << "I was not able to close the file " << fileName << " properly!" << std::endl;
      return false;
+4 −6
Original line number Diff line number Diff line
@@ -12,8 +12,7 @@

#include <iostream>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <cstdio>
#ifdef HAVE_CUDA
   #include <cuda_runtime.h>
#endif
@@ -46,15 +45,15 @@ class File
{
   IOMode mode;

   FILE* file;
   std::FILE* file;

   bool fileOK;

   String fileName;

   size_t writtenElements;
   std::size_t writtenElements;

   size_t readElements;
   std::size_t readElements;

   public:

@@ -99,7 +98,6 @@ class File
	bool close();

	static int verbose;

};

bool fileExists( const String& fileName );
+44 −70
Original line number Diff line number Diff line
@@ -10,6 +10,8 @@

#pragma once 

#include <type_traits>

#include <TNL/File.h>
#include <TNL/Exceptions/CudaSupportMissing.h>

@@ -34,9 +36,9 @@ bool File :: read( Type* buffer,
{
   TNL_ASSERT_GE( _elements, 0, "Number of elements to read must be non-negative." );

   // convert _elements from Index to size_t, which is *unsigned* type
   // convert _elements from Index to std::size_t, which is *unsigned* type
   // (expected by fread etc)
   size_t elements = (size_t) _elements;
   std::size_t elements = (std::size_t) _elements;

   if( ! elements )
      return true;
@@ -50,19 +52,17 @@ bool File :: read( Type* buffer,
      std::cerr << "File " << fileName << " was not opened for reading. " << std::endl;
      return false;
   }

   this->readElements = 0;
   const size_t host_buffer_size = std::min( tnlFileGPUvsCPUTransferBufferSize / sizeof( Type ),
                                             elements );
   void* host_buffer( 0 );
   if( std::is_same< Device, Devices::Host >::value )
   {
      if( fread( buffer,
      if( std::fread( buffer,
                      sizeof( Type ),
                      elements,
                      file ) != elements )
      {
         std::cerr << "I am not able to read the data from the file " << fileName << "." << std::endl;
         perror( "Fread ended with the error code" );
         std::perror( "Fread ended with the error code" );
         return false;
      }
      this->readElements = elements;
@@ -71,33 +71,21 @@ bool File :: read( Type* buffer,
   if( std::is_same< Device, Devices::Cuda >::value )
   {
#ifdef HAVE_CUDA
      /*!***
       * Here we cannot use
       *
       * host_buffer = new Type[ host_buffer_size ];
       *
       * because it does not work for constant types like
       * T = const bool.
       */
      host_buffer = malloc( sizeof( Type ) * host_buffer_size );
      readElements = 0;
      if( ! host_buffer )
      {
         std::cerr << "I am sorry but I cannot allocate supporting buffer on the host for writing data from the GPU to the file "
              << this->getFileName() << "." << std::endl;
         return false;

      }
      const std::size_t host_buffer_size = std::min( tnlFileGPUvsCPUTransferBufferSize / sizeof( Type ),
                                                elements );
      using BaseType = typename std::remove_cv< Type >::type;
      BaseType* host_buffer = new BaseType[ host_buffer_size ];

      while( readElements < elements )
      {
         size_t transfer = std::min( elements - readElements, host_buffer_size );
         size_t transfered = fread( host_buffer, sizeof( Type ), transfer, file );
         std::size_t transfer = std::min( elements - readElements, host_buffer_size );
         std::size_t transfered = std::fread( host_buffer, sizeof( Type ), transfer, file );
         if( transfered != transfer )
         {
            std::cerr << "I am not able to read the data from the file " << fileName << "." << std::endl;
            std::cerr << transfered << " bytes were transfered. " << std::endl;
            perror( "Fread ended with the error code" );
            std::perror( "Fread ended with the error code" );
            delete[] host_buffer;
            return false;
         }

@@ -109,12 +97,12 @@ bool File :: read( Type* buffer,
         {
            std::cerr << "Transfer of data from the CUDA device to the file " << this->fileName
                 << " failed." << std::endl;
            free( host_buffer );
            delete[] host_buffer;
            return false;
         }
         readElements += transfer;
         this->readElements += transfer;
      }
      free( host_buffer );
      delete[] host_buffer;
      return true;
#else
      throw Exceptions::CudaSupportMissing();
@@ -129,9 +117,9 @@ bool File :: write( const Type* buffer,
{
   TNL_ASSERT_GE( _elements, 0, "Number of elements to write must be non-negative." );

   // convert _elements from Index to size_t, which is *unsigned* type
   // convert _elements from Index to std::size_t, which is *unsigned* type
   // (expected by fread etc)
   size_t elements = (size_t) _elements;
   std::size_t elements = (std::size_t) _elements;

   if( ! elements )
      return true;
@@ -146,20 +134,16 @@ bool File :: write( const Type* buffer,
      return false;
   }

   Type* buf = const_cast< Type* >( buffer );
   void* host_buffer( 0 );
   this->writtenElements = 0;
   const size_t host_buffer_size = std::min( tnlFileGPUvsCPUTransferBufferSize / sizeof( Type ),
                                             elements );
   if( std::is_same< Device, Devices::Host >::value )
   {
      if( fwrite( buf,
      if( std::fwrite( buffer,
                       sizeof( Type ),
                       elements,
                       this->file ) != elements )
      {
         std::cerr << "I am not able to write the data to the file " << fileName << "." << std::endl;
         perror( "Fwrite ended with the error code" );
         std::perror( "Fwrite ended with the error code" );
         return false;
      }
      this->writtenElements = elements;
@@ -168,25 +152,14 @@ bool File :: write( const Type* buffer,
   if( std::is_same< Device, Devices::Cuda >::value )
   {
#ifdef HAVE_CUDA
      /*!***
       * Here we cannot use
       *
       * host_buffer = new Type[ host_buffer_size ];
       *
       * because it does not work for constant types like
       * T = const bool.
       */
      host_buffer = malloc( sizeof( Type ) * host_buffer_size );
      if( ! host_buffer )
      {
         std::cerr << "I am sorry but I cannot allocate supporting buffer on the host for writing data from the GPU to the file "
              << this->getFileName() << "." << std::endl;
         return false;
      }
      const std::size_t host_buffer_size = std::min( tnlFileGPUvsCPUTransferBufferSize / sizeof( Type ),
                                                elements );
      using BaseType = typename std::remove_cv< Type >::type;
      BaseType* host_buffer = new BaseType[ host_buffer_size ];

      while( this->writtenElements < elements )
      {
         size_t transfer = std::min( elements - this->writtenElements, host_buffer_size );
         std::size_t transfer = std::min( elements - this->writtenElements, host_buffer_size );
         cudaMemcpy( host_buffer,
                     ( void* ) & ( buffer[ this->writtenElements ] ),
                     transfer * sizeof( Type ),
@@ -195,21 +168,22 @@ bool File :: write( const Type* buffer,
         {
            std::cerr << "Transfer of data from the file " << this->fileName
                 << " to the CUDA device failed." << std::endl;
            free( host_buffer );
            delete[] host_buffer;
            return false;
         }
         if( fwrite( host_buffer,
         if( std::fwrite( host_buffer,
                          sizeof( Type ),
                          transfer,
                          this->file ) != transfer )
         {
            std::cerr << "I am not able to write the data to the file " << fileName << "." << std::endl;
            perror( "Fwrite ended with the error code" );
            std::perror( "Fwrite ended with the error code" );
            delete[] host_buffer;
            return false;
         }
         this->writtenElements += transfer;
      }
      free( host_buffer );
      delete[] host_buffer;
      return true;
#else
      throw Exceptions::CudaSupportMissing();
+24 −0
Original line number Diff line number Diff line
@@ -28,19 +28,24 @@ TEST( FileTest, WriteAndRead )

   int intData( 5 );
   double doubleData[ 3 ] = { 1.0, 2.0, 3.0 };
   const double constDoubleData = 3.14;
   ASSERT_TRUE( file.write( &intData ) );
   ASSERT_TRUE( file.write( doubleData, 3 ) );
   ASSERT_TRUE( file.write( &constDoubleData ) );
   ASSERT_TRUE( file.close() );

   ASSERT_TRUE( file.open( String( "test-file.tnl" ), IOMode::read ) );
   int newIntData;
   double newDoubleData[ 3 ];
   double newConstDoubleData;
   ASSERT_TRUE( file.read( &newIntData, 1 ) );
   ASSERT_TRUE( file.read( newDoubleData, 3 ) );
   ASSERT_TRUE( file.read( &newConstDoubleData, 1 ) );

   EXPECT_EQ( newIntData, intData );
   for( int i = 0; i < 3; i ++ )
      EXPECT_EQ( newDoubleData[ i ], doubleData[ i ] );
   EXPECT_EQ( newConstDoubleData, constDoubleData );
};

#ifdef HAVE_CUDA
@@ -48,11 +53,14 @@ TEST( FileTest, WriteAndReadCUDA )
{
   int intData( 5 );
   float floatData[ 3 ] = { 1.0, 2.0, 3.0 };
   const double constDoubleData = 3.14;

   int* cudaIntData;
   float* cudaFloatData;
   const double* cudaConstDoubleData;
   cudaMalloc( ( void** ) &cudaIntData, sizeof( int ) );
   cudaMalloc( ( void** ) &cudaFloatData, 3 * sizeof( float ) );
   cudaMalloc( ( void** ) &cudaConstDoubleData, sizeof( double ) );
   cudaMemcpy( cudaIntData,
               &intData,
               sizeof( int ),
@@ -61,6 +69,10 @@ TEST( FileTest, WriteAndReadCUDA )
               floatData,
               3 * sizeof( float ),
               cudaMemcpyHostToDevice );
   cudaMemcpy( (void*) cudaConstDoubleData,
               &constDoubleData,
               sizeof( double ),
               cudaMemcpyHostToDevice );

   File file;
   ASSERT_TRUE( file.open( String( "test-file.tnl" ), IOMode::write ) );
@@ -69,19 +81,26 @@ TEST( FileTest, WriteAndReadCUDA )
   ASSERT_TRUE( status );
   status = file.write< float, Devices::Cuda, int >( cudaFloatData, 3 );
   ASSERT_TRUE( status );
   status = file.write< const double, Devices::Cuda >( cudaConstDoubleData );
   ASSERT_TRUE( status );
   ASSERT_TRUE( file.close() );

   ASSERT_TRUE( file.open( String( "test-file.tnl" ), IOMode::read ) );
   int newIntData;
   float newFloatData[ 3 ];
   double newDoubleData;
   int* newCudaIntData;
   float* newCudaFloatData;
   double* newCudaDoubleData;
   cudaMalloc( ( void** ) &newCudaIntData, sizeof( int ) );
   cudaMalloc( ( void** ) &newCudaFloatData, 3 * sizeof( float ) );
   cudaMalloc( ( void** ) &newCudaDoubleData, sizeof( double ) );
   status = file.read< int, Devices::Cuda >( newCudaIntData, 1 );
   ASSERT_TRUE( status );
   status = file.read< float, Devices::Cuda, int >( newCudaFloatData, 3 );
   ASSERT_TRUE( status );
   status = file.read< double, Devices::Cuda >( newCudaDoubleData, 1 );
   ASSERT_TRUE( status );
   cudaMemcpy( &newIntData,
               newCudaIntData,
               sizeof( int ),
@@ -90,10 +109,15 @@ TEST( FileTest, WriteAndReadCUDA )
               newCudaFloatData,
               3 * sizeof( float ),
               cudaMemcpyDeviceToHost );
   cudaMemcpy( &newDoubleData,
               newCudaDoubleData,
               sizeof( double ),
               cudaMemcpyDeviceToHost );

   EXPECT_EQ( newIntData, intData );
   for( int i = 0; i < 3; i ++ )
      EXPECT_EQ( newFloatData[ i ], floatData[ i ] );
   EXPECT_EQ( newDoubleData, constDoubleData );
};
#endif
#endif