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

Reimplementation of vectors, arrays and grids.

parent ea959072
Loading
Loading
Loading
Loading
+30 −32
Original line number Diff line number Diff line
INCLUDE_DIRECTORIES( low-level )
add_subdirectory( implementation )

add_subdirectory( low-level )

set (headers tnlMultiArray.h
             tnlArray.h
             tnlArrayBase.h
             tnlArrayHost.h
             tnlArrayCUDA.h
set (headers tnlArray.h
             tnlAssert.h               
             tnlCurve.h
      	    tnlCuda.h
      	    tnlCudaSupport.h
  		       tnlDataElement.h
  		       tnlDevice.h
  		       tnlFile.h 
  		       tnlFlopsCounter.h
   		    tnlHost.h 
   		    tnlList.h
   		    tnlMultiArray.h
   		    tnlMultiVector.h 
   		    tnlSharedArray.h
   		    tnlSharedVector.h
   		    tnlVector.h 
		       tnlVectorHost.h 
		       tnlVectorCUDA.h  
   		    tnlLogger.h 
   		    tnlObject.h 
   		    tnlStack.h
+18 −0
Original line number Diff line number Diff line
SET( headers cuda-long-vector-kernels.h
             vector-operations.h
             memory-functions.h
             tnlArray_impl.h
             tnlMultiArray1D_impl.h
             tnlMultiArray2D_impl.h
             tnlMultiArray3D_impl.h
             tnlMultiArray4D_impl.h
             tnlMultiVector1D_impl.h
             tnlMultiVector2D_impl.h
             tnlMultiVector3D_impl.h
             tnlMultiVector4D_impl.h            
             tnlSharedArray_impl.h
             tnlSharedVector_impl.h
             tnlVector_impl.h )

INSTALL( FILES ${headers} DESTINATION include/tnl-${tnlVersion}/core/implementation )
+235 −0
Original line number Diff line number Diff line
/***************************************************************************
                          memory-functions.h  -  description
                             -------------------
    begin                : Nov 9, 2012
    copyright            : (C) 2012 by Tomas Oberhuber
    email                : tomas.oberhuber@fjfi.cvut.cz
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef MEMORYFUNCTIONS_H_
#define MEMORYFUNCTIONS_H_

template< typename Element, typename Index >
void allocateMemoryHost( Element*& data,
                         const Index size )
{
   data = new Element[ size ];
}

template< typename Element, typename Index >
void allocateMemoryCuda( Element*& data,
                         const Index size )
{
#ifdef HAVE_CUDA
   if( cudaMalloc( ( void** ) &data,
                   ( size_t ) size * sizeof( ElementType ) ) != cudaSuccess )
      data = 0;
#endif
}

template< typename Element >
bool freeMemoryHost( Element* data )
{
   delete[] data;
   return true;
}

template< typename Element >
bool freeMemoryCuda( Element* data )
{
#ifdef HAVE_CUDA
      cudaFree( data );
      checkCUDAError( __FILE__, __LINE__ );
#endif
   return true;
}

template< typename Element, typename Index >
bool setMemoryHost( Element* data,
                    const Element& value,
                    const Index size )
{
   for( Index i = 0; i < size; i ++ )
      data[ i ] = value;
}

template< typename Element, typename Index >
bool setMemoryCuda( Element* data,
                    const Element& value,
                    const Index size )
{
#ifdef HAVE_CUDA
      dim3 blockSize, gridSize;
      blockSize. x = 512;
      gridSize. x = size / 512 + 1;

      // TODO: fix this -- the maximum grid size may not by enough
      tnlVectorCUDASetValueKernel<<< gridSize, blockSize >>>( data,
                                                              size,
                                                              value );
#else
      cerr << "I am sorry but CUDA support is missing on this system " << __FILE__ << " line " << __LINE__ << "." << endl;
#endif

}

template< typename Element, typename Index >
bool copyMemoryHostToHost( Element* destination,
                           const Element* source,
                           const Index size )
{
   for( Index i = 0; i < size; i ++ )
      destination[ i ] = source[ i ];
   return true;
}

template< typename Element, typename Index >
bool copyMemoryHostToCuda( Element* destination,
                           const Element* source,
                           const Index size )
{
#ifdef HAVE_CUDA
   if( cudaMemcpy( destination,
                   source,
                   size * sizeof( Elemen ),
                   cudaMemcpyHostToDevice ) != cudaSuccess )
   {
      cerr << "Transfer of data from host to CUDA device failed." << endl;
      return false;
   }
   return true;
#else
   cerr << "CUDA support is missing in this system." << endl;
   return false;
#endif
}


template< typename Element, typename Index >
bool copyMemoryCudaToHost( Element* destination,
                           const Element* source,
                           const Index size )
{
#ifdef HAVE_CUDA
   if( cudaMemcpy( destination,
                   source,
                   size * sizeof( Elemen ),
                   cudaMemcpyDeviceToHost ) != cudaSuccess )
   {
      cerr << "Transfer of data from CUDA device to host failed." << endl;
      return false;
   }
   return true;
#else
   cerr << "CUDA support is missing in this system." << endl;
   return false;
#endif
}

template< typename Element, typename Index >
bool copyMemoryCudaToCuda( Element* destination,
                           const Element* source,
                           const Index size )
{
#ifdef HAVE_CUDA
   if( cudaMemcpy( destination,
                   source,
                   size * sizeof( Element ),
                   cudaMemcpyDeviceToDevice ) != cudaSuccess )
   {
      cerr << "Transfer of data from CUDA device to device failed." << endl;
      return false;
   }
   return true;
#else
   cerr << "CUDA support is missing in this system." << endl;
   return false;
#endif
}

template< typename Element, typename Index >
bool compareMemoryHost( const Element* data1,
                        const Element* data2,
                        const Index size )
{
   for( Index i = 0; i < size; i ++ )
      if( data1[ i ] != data2[ i ] )
         return false;
   return true;
}

template< typename Element, typename Index >
bool compareMemoryHostCuda( const Element* hostData,
                               const Element* deviceData,
                               const Index size )
{
#ifdef HAVE_CUDA
   Index host_buffer_size = :: Min( ( Index ) ( tnlGPUvsCPUTransferBufferSize / sizeof( Element ) ),
                                                size );
   Element* host_buffer = new Element[ host_buffer_size ];
   if( ! host_buffer )
   {
      cerr << "I am sorry but I cannot allocate supporting buffer on the host for comparing data between CUDA GPU and CPU." << endl;
      return false;
   }
   Index compared( 0 );
   while( compared < this -> getSize() )
   {
      Index transfer = Min( this -> getSize() - compared, host_buffer_size );
      if( cudaMemcpy( ( void* ) host_buffer,
                      ( void* ) & ( deviceData[ compared ] ),
                      transfer * sizeof( Element ),
                      cudaMemcpyDeviceToHost ) != cudaSuccess )
      {
         cerr << "Transfer of data to the element number of the CUDA long vector " << this -> getName()
              << " from the device failed." << endl;
         checkCUDAError( __FILE__, __LINE__ );
         delete[] host_buffer;
         return false;
      }
      Index bufferIndex( 0 );
      while( bufferIndex < transfer &&
             host_buffer[ bufferIndex ] == hostData[ compared ] ) )
      {
         bufferIndex ++;
         compared ++;
      }
      if( bufferIndex < transfer )
      {
         delete[] host_buffer;
         return false;
      }
   }
   delete[] host_buffer;
   return true;
#else
   cerr << "I am sorry but CUDA support is missing on this system " << __FILE__ << " line " << __LINE__ << "." << endl;
   return false;
#endif
}

template< typename Element, typename Index >
bool compareMemoryCuda( const Element* deviceData1,
                           const Element* deviceData2,
                           const Index size )
{
#ifdef HAVE_CUDA
   return tnlCUDALongVectorComparison( size,
                                       deviceData1,
                                       deviceData2 ) )
#else
   cerr << "I am sorry but CUDA support is missing on this system " << __FILE__ << " line " << __LINE__ << "." << endl;
   return false;
#endif
}

#endif /* MEMORYFUNCTIONS_H_ */
+352 −0
Original line number Diff line number Diff line
/***************************************************************************
                          tnlArray.h  -  description
                             -------------------
    begin                : Nov 8, 2012
    copyright            : (C) 2012 by Tomas Oberhuber
    email                : tomas.oberhuber@fjfi.cvut.cz
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef TNLARRAY_H_IMPLEMENTATION
#define TNLARRAY_H_IMPLEMENTATION

#include <core/tnlFile.h>
#include <core/mfuncs.h>
#include <core/param-types.h>

//namespace implementation
//{

template< typename Element,
          typename Device,
          typename Index >
tnlArray< Element, Device, Index > :: tnlArray()
: size( 0 ), data( 0 )
{
};

template< typename Element,
          typename Device,
          typename Index >
tnlArray< Element, Device, Index > :: tnlArray( const tnlString& name )
: size( 0 ), data( 0 )
{
   this -> setName( name );
};

template< typename Element,
          typename Device,
          typename Index >
tnlString tnlArray< Element, Device, Index > :: getType() const
{
   return tnlString( "tnlArray< " ) +
                     getParameterType< Element >() +
                     Device :: getDeviceType() +
                     getParameterType< Index >() +
                     " >";
};

template< typename Element,
          typename Device,
          typename Index >
bool tnlArray< Element, Device, Index > :: setSize( const Index size )
{
   tnlAssert( size >= 0,
              cerr << "You try to set size of tnlArray to negative value."
                   << "Name: " << this -> getName() << endl
                   << "New size: " << size << endl );
   if( this -> size && this -> size == size ) return true;
   if( this -> data )
   {
      Device :: freeMemory( this -> data );
      this -> data = 0;
   }
   this -> size = size;
   Device :: allocateMemory( this -> data, size + 1 );
   if( ! this -> data )
   {
      cerr << "I am not able to allocate new array with size "
           << ( double ) this -> size * sizeof( ElementType ) / 1.0e9 << " GB on host for "
           << this -> getName() << "." << endl;
      this -> size = 0;
      return false;
   }
   ( this -> data ) ++;
   return true;
};

template< typename Element,
          typename Device,
          typename Index >
   template< typename Array >
bool tnlArray< Element, Device, Index > :: setLike( const Array& array )
{
   tnlAssert( array. getSize() >= 0,
              cerr << "You try to set size of tnlArray to negative value."
                   << "Name: " << this -> getName() << endl
                   << "Array name:" << array. getName() <<
                   << "Array size: " << array. getSize() << endl );
   return setSize( array. getSize() );
};

template< typename Element,
          typename Device,
          typename Index >
void tnlArray< Element, Device, Index > :: swap( tnlArray< Element, Device, Index >& array )
{
   swap( this -> size, array. size );
   swap( this -> data, array. data );
};

template< typename Element,
          typename Device,
          typename Index >
void tnlArray< Element, Device, Index > :: reset()
{
   this -> size = 0;
   this -> data = 0;
};

template< typename Element,
          typename Device,
          typename Index >
Index tnlArray< Element, Device, Index > :: getSize() const
{
   return this -> size;
}

template< typename Element,
          typename Device,
          typename Index >
void tnlArray< Element, Device, Index > :: setElement( const Element& x, Index i )
{
   tnlAssert( 0 <= i && i < this -> getSize(),
              cerr << "Wrong index for setElement method in tnlArray with name "
                   << this -> getName()
                   << " index is " << i
                   << " and array size is " << this -> getSize() );
   return Device :: setArrayElement( this -> data, x, i );
};

template< typename Element,
          typename Device,
          typename Index >
Element tnlArray< Element, Device, Index > :: getElement( Index i ) const
{
   tnlAssert( 0 <= i && i < this -> getSize(),
              cerr << "Wrong index for getElement method in tnlArray with name "
                   << this -> getName()
                   << " index is " << i
                   << " and array size is " << this -> getSize() );
   return Device :: getArrayElement( this -> data, i );
};

template< typename Element,
          typename Device,
          typename Index >
Element& tnlArray< Element, Device, Index > :: operator[] ( Index i )
{
   tnlAssert( 0 <= i && i < this -> getSize(),
              cerr << "Wrong index for operator[] in tnlArray with name "
                   << this -> getName()
                   << " index is " << i
                   << " and array size is " << this -> getSize() );
   // TODO: add static assert - this does not make sense for tnlCudaDevice
   return Device :: getArrayElementReference( this -> data, i );
};

template< typename Element,
          typename Device,
          typename Index >
const Element& tnlArray< Element, Device, Index > :: operator[] ( Index i ) const
{
   tnlAssert( 0 <= i && i < this -> getSize(),
              cerr << "Wrong index for operator[] in tnlArray with name "
                   << this -> getName()
                   << " index is " << i
                   << " and array size is " << this -> getSize() );
   // TODO: add static assert - this does not make sense for tnlCudaDevice
   return Device :: getArrayElementReference( this -> data, i );
};

template< typename Element,
          typename Device,
          typename Index >
   template< typename Array >
tnlArray< Element, Device, Index >& tnlArray< Element, Device, Index > :: operator = ( const Array& array )
{
   typedef typename Array :: ElementType ArrayElement;
   typedef typename Array :: IndexType ArrayIndex;
   typedef typename Array :: DeviceType ArrayDevice;
   
   // TODO: check this
   /*STATIC_ASSERT( ElementType == Array :: ElementType &&
                  IndexType == Array :: IndexType,
                  "Cannot assign arrays with different element types or index types (in tnlArray)" );*/
   tnlAssert( array. getSize() == this -> getSize(),
           cerr << "Source name: " << a. getName() << endl
                << "Source size: " << a. getSize() << endl
                << "Target name: " << this -> getName() << endl
                << "Target size: " << this -> getSize() << endl );
   Device :: template memcpy< ArrayElement,
                              ArrayIndex,
                              ArrayDevice >
                   ( this -> getData(),
                     array. getData(),
                     array. getSize() );
   return ( *this );
};

template< typename Element,
          typename Device,
          typename Index >
   template< typename Array >
bool tnlArray< Element, Device, Index > :: operator == ( const Array& array ) const
{
   typedef typename Array :: ElementType ArrayElement;
   typedef typename Array :: IndexType ArrayIndex;
   typedef typename Array :: DeviceType ArrayDevice;
   // TODO: check this
   /*STATIC_ASSERT( ElementType == Array :: ElementType &&
                  IndexType == Array :: IndexType,
                  "Cannot assign arrays with different element types or index types (in tnlArray)" );*/
   tnlAssert( array. getSize() == this -> getSize(),
           cerr << "Source name: " << a. getName() << endl
                << "Source size: " << a. getSize() << endl
                << "Target name: " << this -> getName() << endl
                << "Target size: " << this -> getSize() << endl );
   return Device :: template memcmp< ArrayElement,
                                     ArrayIndex,
                                     ArrayDevice >
                                   ( this -> getData(),
                                     array. getData(),
                                     array. getSize() );
}

template< typename Element,
          typename Device,
          typename Index >
   template< typename Array >
bool tnlArray< Element, Device, Index > :: operator != ( const Array& array ) const
{
   // TODO: check this
   /*STATIC_ASSERT( ElementType == Array :: ElementType &&
                  IndexType == Array :: IndexType,
                  "Cannot assign arrays with different element types or index types (in tnlArray)" );*/
   tnlAssert( array. getSize() == this -> getSize(),
           cerr << "Source name: " << a. getName() << endl
                << "Source size: " << a. getSize() << endl
                << "Target name: " << this -> getName() << endl
                << "Target size: " << this -> getSize() << endl );
   return ! ( ( *this ) == array );
}

template< typename Element,
          typename Device,
          typename Index >
void tnlArray< Element, Device, Index > :: setValue( const Element& e )
{
   tnlAssert( this -> size != 0,
              cerr << "Array name is " << this -> getName() );
   Device :: memset( this -> getData(), this -> getSize(), e );
}

template< typename Element,
          typename Device,
          typename Index >
const Element* tnlArray< Element, Device, Index > :: getData() const
{
   return this -> data;
}

template< typename Element,
          typename Device,
          typename Index >
Element* tnlArray< Element, Device, Index > :: getData()
{
   return this -> data;
}

template< typename Element,
          typename Device,
          typename Index >
tnlArray< Element, Device, Index > :: operator bool() const
{
   return data != 0;
};


template< typename Element,
          typename Device,
          typename Index >
   template< typename IndexType2 >
void tnlArray< Element, Device, Index > :: touch( IndexType2 touches ) const
{
   //TODO: implement
};

template< typename Element,
          typename Device,
          typename Index >
bool tnlArray< Element, Device, Index > :: save( tnlFile& file ) const
{
   tnlAssert( this -> size != 0,
              cerr << "You try to save empty vector. Its name is " << this -> getName() );
   if( ! tnlObject :: save( file ) )
      return false;
   if( ! file. write( &this -> size, 1 ) )
      return false;
   if( ! file. write< Element, Device, Index >( this -> data, this -> size ) )
   {
      cerr << "I was not able to WRITE tnlArray " << this -> getName()
           << " with size " << this -> getSize() << endl;
      return false;
   }
   return true;
};

template< typename Element,
          typename Device,
          typename Index >
bool tnlArray< Element, Device, Index > :: load( tnlFile& file )
{
   if( ! tnlObject :: load( file ) )
      return false;
   int _size;
   if( ! file. read( &_size, 1 ) )
      return false;
   if( _size <= 0 )
   {
      cerr << "Error: The size " << _size << " of the file is not a positive number." << endl;
      return false;
   }
   setSize( _size );
   if( ! file. read< Element, Device, Index >( this -> data, this -> size ) )
   {
      cerr << "I was not able to READ tnlArray " << this -> getName()
           << " with size " << this -> getSize() << endl;
      return false;
   }
   return true;
}

template< typename Element,
          typename Device,
          typename Index >
tnlArray< Element, Device, Index > :: ~tnlArray()
{
   if( this -> data )
      Device :: freeMemory( this -> data );
}

//}; // namespace implementation

#endif /* TNLARRAY_H_IMPLEMENTATION */
Loading