From fcb368b75abc9fbce5a0e4cf8e31c18935fc1fdb Mon Sep 17 00:00:00 2001 From: Tomas Oberhuber <tomas.oberhuber@fjfi.cvut.cz> Date: Wed, 15 Jan 2020 18:05:53 +0100 Subject: [PATCH] Forwarding dense matrix methods calls to DenseMatrixView. --- src/TNL/Containers/Segments/EllpackView.h | 2 + src/TNL/Containers/Segments/EllpackView.hpp | 13 ++ src/TNL/Matrices/Dense.h | 4 +- src/TNL/Matrices/Dense.hpp | 136 +++++--------------- src/TNL/Matrices/DenseMatrixView.h | 10 -- src/TNL/Matrices/DenseMatrixView.hpp | 77 ++++------- src/UnitTests/Matrices/DenseMatrixTest.h | 4 +- 7 files changed, 71 insertions(+), 175 deletions(-) diff --git a/src/TNL/Containers/Segments/EllpackView.h b/src/TNL/Containers/Segments/EllpackView.h index 737810498a..f64b04068e 100644 --- a/src/TNL/Containers/Segments/EllpackView.h +++ b/src/TNL/Containers/Segments/EllpackView.h @@ -104,6 +104,8 @@ class EllpackView template< typename Fetch, typename Reduction, typename ResultKeeper, typename Real, typename... Args > void allReduction( Fetch& fetch, Reduction& reduction, ResultKeeper& keeper, const Real& zero, Args... args ) const; + EllpackView& operator=( const EllpackView& view ); + void save( File& file ) const; void load( File& file ); diff --git a/src/TNL/Containers/Segments/EllpackView.hpp b/src/TNL/Containers/Segments/EllpackView.hpp index 21be886541..719a349a98 100644 --- a/src/TNL/Containers/Segments/EllpackView.hpp +++ b/src/TNL/Containers/Segments/EllpackView.hpp @@ -291,6 +291,19 @@ allReduction( Fetch& fetch, Reduction& reduction, ResultKeeper& keeper, const Re this->segmentsReduction( 0, this->getSegmentsCount(), fetch, reduction, keeper, zero, args... ); } +template< typename Device, + typename Index, + bool RowMajorOrder, + int Alignment > +EllpackView< Device, Index, RowMajorOrder, Alignment >& +EllpackView< Device, Index, RowMajorOrder, Alignment >:: +operator=( const EllpackView< Device, Index, RowMajorOrder, Alignment >& view ) +{ + this->segmentSize = view.segmentSize; + this->size = view.size; + this->alignedSize = view.alignedSize; +} + template< typename Device, typename Index, bool RowMajorOrder, diff --git a/src/TNL/Matrices/Dense.h b/src/TNL/Matrices/Dense.h index 485c947010..2e71316e94 100644 --- a/src/TNL/Matrices/Dense.h +++ b/src/TNL/Matrices/Dense.h @@ -168,7 +168,7 @@ class Dense : public Matrix< Real, Device, Index > const RealType& omega = 1.0 ) const; // copy assignment - //Dense& operator=( const Dense& matrix ); + Dense& operator=( const Dense& matrix ); // cross-device copy assignment template< typename Real_, typename Device_, typename Index_, bool RowMajorOrder_, typename RealAlocator_ > @@ -200,6 +200,8 @@ class Dense : public Matrix< Real, Device, Index > friend class DenseDeviceDependentCode< DeviceType >; SegmentsType segments; + + ViewType view; }; } // namespace Matrices diff --git a/src/TNL/Matrices/Dense.hpp b/src/TNL/Matrices/Dense.hpp index 7e6f379486..b8fa969074 100644 --- a/src/TNL/Matrices/Dense.hpp +++ b/src/TNL/Matrices/Dense.hpp @@ -76,10 +76,7 @@ String Dense< Real, Device, Index, RowMajorOrder, RealAllocator >:: getSerializationType() { - return String( "Matrices::Dense< " ) + - TNL::getSerializationType< RealType >() + ", [any_device], " + - TNL::getSerializationType< IndexType >() + ", " + - ( RowMajorOrder ? "true" : "false" ) + ", [any_allocator] >"; + return ViewType::getSerializationType(); } template< typename Real, @@ -108,6 +105,7 @@ setDimensions( const IndexType rows, this->segments.setSegmentsSizes( rows, columns ); this->values.setSize( rows * columns ); this->values = 0.0; + this->view = this->getView(); } template< typename Real, @@ -145,19 +143,7 @@ void Dense< Real, Device, Index, RowMajorOrder, RealAllocator >:: getCompressedRowLengths( Vector& rowLengths ) const { - rowLengths.setSize( this->getRows() ); - rowLengths = 0; - auto rowLengths_view = rowLengths.getView(); - auto fetch = [] __cuda_callable__ ( IndexType row, IndexType column, const RealType& value ) -> IndexType { - return ( value != 0.0 ); - }; - auto reduce = [] __cuda_callable__ ( IndexType& aux, const IndexType a ) { - aux += a; - }; - auto keep = [=] __cuda_callable__ ( const IndexType rowIdx, const IndexType value ) mutable { - rowLengths_view[ rowIdx ] = value; - }; - this->allRowsReduction( fetch, reduce, keep, 0 ); + this->view.getCompressedRowLengths( rowLengths ); } template< typename Real, @@ -197,11 +183,7 @@ template< typename Real, typename RealAllocator > Index Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::getNumberOfNonzeroMatrixElements() const { - const auto values_view = this->values.getConstView(); - auto fetch = [=] __cuda_callable__ ( const IndexType i ) -> IndexType { - return ( values_view[ i ] != 0.0 ); - }; - return Algorithms::Reduction< DeviceType >::reduce( this->values.getSize(), std::plus<>{}, fetch, 0 ); + return this->view.getNumberOfNonzeroMatrixElements(); } template< typename Real, @@ -221,7 +203,7 @@ template< typename Real, typename RealAllocator > void Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::setValue( const Real& value ) { - this->values = value; + this->view.setValue( value ); } template< typename Real, @@ -233,8 +215,7 @@ __cuda_callable__ auto Dense< Real, Device, Index, RowMajorOrder, RealAllocator >:: getRow( const IndexType& rowIdx ) const -> const RowView { - TNL_ASSERT_LT( rowIdx, this->getRows(), "Row index is larger than number of matrix rows." ); - return RowView( this->segments.getSegmentView( rowIdx ), this->values.getView() ); + return this->view.getRow( rowIdx ); } template< typename Real, @@ -246,8 +227,7 @@ __cuda_callable__ auto Dense< Real, Device, Index, RowMajorOrder, RealAllocator >:: getRow( const IndexType& rowIdx ) -> RowView { - TNL_ASSERT_LT( rowIdx, this->getRows(), "Row index is larger than number of matrix rows." ); - return RowView( this->segments.getSegmentView( rowIdx ), this->values.getView() ); + return this->view.getRow( rowIdx ); } template< typename Real, @@ -259,12 +239,7 @@ __cuda_callable__ Real& Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::operator()( const IndexType row, const IndexType column ) { - TNL_ASSERT_GE( row, 0, "Row index must be non-negative." ); - TNL_ASSERT_LT( row, this->getRows(), "Row index is out of bounds." ); - TNL_ASSERT_GE( column, 0, "Column index must be non-negative." ); - TNL_ASSERT_LT( column, this->getColumns(), "Column index is out of bounds." ); - - return this->values.operator[]( this->getElementIndex( row, column ) ); + return this->view.operator()( row, column ); } template< typename Real, @@ -276,12 +251,7 @@ __cuda_callable__ const Real& Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::operator()( const IndexType row, const IndexType column ) const { - TNL_ASSERT_GE( row, 0, "Row index must be non-negative." ); - TNL_ASSERT_LT( row, this->getRows(), "Row index is out of bounds." ); - TNL_ASSERT_GE( column, 0, "Column index must be non-negative." ); - TNL_ASSERT_LT( column, this->getColumns(), "Column index is out of bounds." ); - - return this->values.operator[]( this->getElementIndex( row, column ) ); + return this->view.operator()( row, column ); } template< typename Real, @@ -295,7 +265,7 @@ setElement( const IndexType row, const IndexType column, const RealType& value ) { - this->values.setElement( this->getElementIndex( row, column ), value ); + this->view.setElement( row, column, value ); } template< typename Real, @@ -310,13 +280,7 @@ addElement( const IndexType row, const RealType& value, const RealType& thisElementMultiplicator ) { - const IndexType elementIndex = this->getElementIndex( row, column ); - if( thisElementMultiplicator == 1.0 ) - this->values.setElement( elementIndex, - this->values.getElement( elementIndex ) + value ); - else - this->values.setElement( elementIndex, - thisElementMultiplicator * this->values.getElement( elementIndex ) + value ); + this->view.addElement( row, column, value, thisElementMultiplicator ); } template< typename Real, @@ -329,7 +293,7 @@ Dense< Real, Device, Index, RowMajorOrder, RealAllocator >:: getElement( const IndexType row, const IndexType column ) const { - return this->values.getElement( this->getElementIndex( row, column ) ); + return this->view.getElement( row, column ); } template< typename Real, @@ -342,12 +306,7 @@ void Dense< Real, Device, Index, RowMajorOrder, RealAllocator >:: rowsReduction( IndexType first, IndexType last, Fetch& fetch, Reduce& reduce, Keep& keep, const FetchValue& zero ) const { - const auto values_view = this->values.getConstView(); - auto fetch_ = [=] __cuda_callable__ ( IndexType rowIdx, IndexType columnIdx, IndexType globalIdx, bool& compute ) mutable -> decltype( fetch( IndexType(), IndexType(), RealType() ) ) { - return fetch( rowIdx, columnIdx, values_view[ globalIdx ] ); - return zero; - }; - this->segments.segmentsReduction( first, last, fetch_, reduce, keep, zero ); + this->view.rowsReduction( first, last, fetch, reduce, keep, zero ); } template< typename Real, @@ -373,12 +332,7 @@ void Dense< Real, Device, Index, RowMajorOrder, RealAllocator >:: forRows( IndexType first, IndexType last, Function& function ) const { - const auto values_view = this->values.getConstView(); - auto f = [=] __cuda_callable__ ( IndexType rowIdx, IndexType columnIdx, IndexType globalIdx ) mutable -> bool { - function( rowIdx, columnIdx, globalIdx, values_view[ globalIdx ] ); - return true; - }; - this->segments.forSegments( first, last, f ); + this->view.forRows( first, last, function ); } template< typename Real, @@ -391,12 +345,7 @@ void Dense< Real, Device, Index, RowMajorOrder, RealAllocator >:: forRows( IndexType first, IndexType last, Function& function ) { - auto values_view = this->values.getView(); - auto f = [=] __cuda_callable__ ( IndexType rowIdx, IndexType columnIdx, IndexType globalIdx ) mutable -> bool { - function( rowIdx, columnIdx, globalIdx, values_view[ globalIdx ] ); - return true; - }; - this->segments.forSegments( first, last, f ); + this->view.forRows( first, last, function ); } template< typename Real, @@ -435,11 +384,7 @@ __cuda_callable__ typename Vector::RealType Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::rowVectorProduct( const IndexType row, const Vector& vector ) const { - RealType sum( 0.0 ); - // TODO: Fix this - //for( IndexType column = 0; column < this->getColumns(); column++ ) - // sum += this->getElementFast( row, column ) * vector[ column ]; - return sum; + return this->view.rowVectorProduct( row, vector ); } template< typename Real, @@ -453,27 +398,7 @@ void Dense< Real, Device, Index, RowMajorOrder, RealAllocator >:: vectorProduct( const InVector& inVector, OutVector& outVector ) const { - TNL_ASSERT( this->getColumns() == inVector.getSize(), - std::cerr << "Matrix columns: " << this->getColumns() << std::endl - << "Vector size: " << inVector.getSize() << std::endl ); - TNL_ASSERT( this->getRows() == outVector.getSize(), - std::cerr << "Matrix rows: " << this->getRows() << std::endl - << "Vector size: " << outVector.getSize() << std::endl ); - - //DeviceDependentCode::vectorProduct( *this, inVector, outVector ); - const auto inVectorView = inVector.getConstView(); - auto outVectorView = outVector.getView(); - const auto valuesView = this->values.getConstView(); - auto fetch = [=] __cuda_callable__ ( IndexType row, IndexType column, IndexType offset, bool& compute ) -> RealType { - return valuesView[ offset ] * inVectorView[ column ]; - }; - auto reduction = [] __cuda_callable__ ( RealType& sum, const RealType& value ) { - sum += value; - }; - auto keeper = [=] __cuda_callable__ ( IndexType row, const RealType& value ) mutable { - outVectorView[ row ] = value; - }; - this->segments.segmentsReduction( 0, this->getRows(), fetch, reduction, keeper, ( RealType ) 0.0 ); + this->view.vectorProduct( inVector, outVector ); } template< typename Real, @@ -959,7 +884,7 @@ void Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::performSORItera x[ row ] = ( 1.0 - omega ) * x[ row ] + omega / diagonalValue * ( b[ row ] - sum ); } -/*template< typename Real, +template< typename Real, typename Device, typename Index, bool RowMajorOrder, @@ -968,7 +893,9 @@ Dense< Real, Device, Index, RowMajorOrder, RealAllocator >& Dense< Real, Device, Index, RowMajorOrder, RealAllocator >:: operator=( const Dense< Real, Device, Index, RowMajorOrder, RealAllocator >& matrix ) { - const IndexType bufferRowsCount( 128 ); + setLike( matrix ); + this->values = matrix.values; + /*const IndexType bufferRowsCount( 128 ); const IndexType columns = this->getColumns(); const size_t bufferSize = bufferRowsCount * columns; Containers::Vector< RealType, Device, IndexType, RealAllocatorType > sourceValuesBuffer( bufferSize ); @@ -1000,8 +927,8 @@ operator=( const Dense< Real, Device, Index, RowMajorOrder, RealAllocator >& mat this->forRows( baseRow, lastRow, f2 ); baseRow += bufferRowsCount; } - return *this; -}*/ + return *this;*/ +} template< typename Real, typename Device, @@ -1101,7 +1028,7 @@ template< typename Real, typename RealAllocator > void Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::save( const String& fileName ) const { - Object::save( fileName ); + this->view.save( fileName ); } template< typename Real, @@ -1121,7 +1048,7 @@ template< typename Real, typename RealAllocator > void Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::save( File& file ) const { - Matrix< Real, Device, Index >::save( file ); + this->view.save( file ); } template< typename Real, @@ -1141,13 +1068,7 @@ template< typename Real, typename RealAllocator > void Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::print( std::ostream& str ) const { - for( IndexType row = 0; row < this->getRows(); row++ ) - { - str <<"Row: " << row << " -> "; - for( IndexType column = 0; column < this->getColumns(); column++ ) - str << " Col:" << column << "->" << this->getElement( row, column ) << "\t"; - str << std::endl; - } + this->view.print( str ); } template< typename Real, @@ -1156,8 +1077,9 @@ template< typename Real, bool RowMajorOrder, typename RealAllocator > __cuda_callable__ -Index Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::getElementIndex( const IndexType row, - const IndexType column ) const +Index +Dense< Real, Device, Index, RowMajorOrder, RealAllocator >:: +getElementIndex( const IndexType row, const IndexType column ) const { return this->segments.getGlobalIndex( row, column ); } diff --git a/src/TNL/Matrices/DenseMatrixView.h b/src/TNL/Matrices/DenseMatrixView.h index 9bad424b2a..d963dd7c3e 100644 --- a/src/TNL/Matrices/DenseMatrixView.h +++ b/src/TNL/Matrices/DenseMatrixView.h @@ -171,22 +171,12 @@ class DenseMatrixView : public MatrixView< Real, Device, Index > Vector2& x, const RealType& omega = 1.0 ) const; - // copy assignment DenseMatrixView& operator=( const DenseMatrixView& matrix ); - // cross-device copy assignment - template< typename Real2, typename Device2, typename Index2, - typename = typename Enabler< Device2 >::type > - DenseMatrixView& operator=( const DenseMatrixView< Real2, Device2, Index2 >& matrix ); - void save( const String& fileName ) const; - void load( const String& fileName ); - void save( File& file ) const; - void load( File& file ); - void print( std::ostream& str ) const; protected: diff --git a/src/TNL/Matrices/DenseMatrixView.hpp b/src/TNL/Matrices/DenseMatrixView.hpp index 21f6d79ef5..527915d55f 100644 --- a/src/TNL/Matrices/DenseMatrixView.hpp +++ b/src/TNL/Matrices/DenseMatrixView.hpp @@ -83,7 +83,7 @@ getSerializationType() { return String( "Matrices::Dense< " ) + TNL::getSerializationType< RealType >() + ", [any_device], " + - TNL::getSerializationType< IndexType >() + + TNL::getSerializationType< IndexType >() + ", " + ( RowMajorOrder ? "true" : "false" ) + ", [any_allocator] >"; } @@ -321,7 +321,7 @@ forRows( IndexType first, IndexType last, Function& function ) const { const auto values_view = this->values.getConstView(); auto f = [=] __cuda_callable__ ( IndexType rowIdx, IndexType columnIdx, IndexType globalIdx ) mutable -> bool { - function( rowIdx, columnIdx, values_view[ globalIdx ] ); + function( rowIdx, columnIdx, columnIdx, values_view[ globalIdx ] ); return true; }; this->segments.forSegments( first, last, f ); @@ -339,7 +339,7 @@ forRows( IndexType first, IndexType last, Function& function ) { auto values_view = this->values.getView(); auto f = [=] __cuda_callable__ ( IndexType rowIdx, IndexType columnIdx, IndexType globalIdx ) mutable -> bool { - function( rowIdx, columnIdx, values_view[ globalIdx ] ); + function( rowIdx, columnIdx, globalIdx, values_view[ globalIdx ] ); return true; }; this->segments.forSegments( first, last, f ); @@ -395,14 +395,22 @@ template< typename Real, void DenseMatrixView< Real, Device, Index, RowMajorOrder >::vectorProduct( const InVector& inVector, OutVector& outVector ) const { - TNL_ASSERT( this->getColumns() == inVector.getSize(), - std::cerr << "Matrix columns: " << this->getColumns() << std::endl - << "Vector size: " << inVector.getSize() << std::endl ); - TNL_ASSERT( this->getRows() == outVector.getSize(), - std::cerr << "Matrix rows: " << this->getRows() << std::endl - << "Vector size: " << outVector.getSize() << std::endl ); - - //DeviceDependentCode::vectorProduct( *this, inVector, outVector ); + TNL_ASSERT_EQ( this->getColumns(), inVector.getSize(), "Matrix columns count differs with input vector size." ); + TNL_ASSERT_EQ( this->getRows(), outVector.getSize(), "Matrix rows count differs with output vector size." ); + + const auto inVectorView = inVector.getConstView(); + auto outVectorView = outVector.getView(); + const auto valuesView = this->values.getConstView(); + auto fetch = [=] __cuda_callable__ ( IndexType row, IndexType column, IndexType offset, bool& compute ) -> RealType { + return valuesView[ offset ] * inVectorView[ column ]; + }; + auto reduction = [] __cuda_callable__ ( RealType& sum, const RealType& value ) { + sum += value; + }; + auto keeper = [=] __cuda_callable__ ( IndexType row, const RealType& value ) mutable { + outVectorView[ row ] = value; + }; + this->segments.segmentsReduction( 0, this->getRows(), fetch, reduction, keeper, ( RealType ) 0.0 ); } template< typename Real, @@ -885,39 +893,18 @@ void DenseMatrixView< Real, Device, Index, RowMajorOrder >::performSORIteration( } -// copy assignment template< typename Real, typename Device, typename Index, bool RowMajorOrder > DenseMatrixView< Real, Device, Index, RowMajorOrder >& -DenseMatrixView< Real, Device, Index, RowMajorOrder >::operator=( const DenseMatrixView& matrix ) -{ - this->setLike( matrix ); - this->values = matrix.values; - return *this; -} - -// cross-device copy assignment -template< typename Real, - typename Device, - typename Index, - bool RowMajorOrder > - template< typename Real2, typename Device2, typename Index2, typename > -DenseMatrixView< Real, Device, Index, RowMajorOrder >& -DenseMatrixView< Real, Device, Index, RowMajorOrder >::operator=( const DenseMatrixView< Real2, Device2, Index2 >& matrix ) +DenseMatrixView< Real, Device, Index, RowMajorOrder >:: +operator=( const DenseMatrixView& matrix ) { - static_assert( std::is_same< Device, Devices::Host >::value || std::is_same< Device, Devices::Cuda >::value, - "unknown device" ); - static_assert( std::is_same< Device2, Devices::Host >::value || std::is_same< Device2, Devices::Cuda >::value, - "unknown device" ); - - this->setLike( matrix ); - - throw Exceptions::NotImplementedError("Cross-device assignment for the Dense format is not implemented yet."); + MatrixView< Real, Device, Index >::operator=( matrix ); + this->segments = matrix.segments; } - template< typename Real, typename Device, typename Index, @@ -927,15 +914,6 @@ void DenseMatrixView< Real, Device, Index, RowMajorOrder >::save( const String& Object::save( fileName ); } -template< typename Real, - typename Device, - typename Index, - bool RowMajorOrder > -void DenseMatrixView< Real, Device, Index, RowMajorOrder >::load( const String& fileName ) -{ - Object::load( fileName ); -} - template< typename Real, typename Device, typename Index, @@ -945,15 +923,6 @@ void DenseMatrixView< Real, Device, Index, RowMajorOrder >::save( File& file ) c MatrixView< Real, Device, Index >::save( file ); } -template< typename Real, - typename Device, - typename Index, - bool RowMajorOrder > -void DenseMatrixView< Real, Device, Index, RowMajorOrder >::load( File& file ) -{ - MatrixView< Real, Device, Index >::load( file ); -} - template< typename Real, typename Device, typename Index, diff --git a/src/UnitTests/Matrices/DenseMatrixTest.h b/src/UnitTests/Matrices/DenseMatrixTest.h index 0f71580100..a3e7e8f61e 100644 --- a/src/UnitTests/Matrices/DenseMatrixTest.h +++ b/src/UnitTests/Matrices/DenseMatrixTest.h @@ -1234,9 +1234,7 @@ void test_SaveAndLoad() ASSERT_NO_THROW( savedMatrix.save( TEST_FILE_NAME ) ); - Matrix loadedMatrix; - loadedMatrix.reset(); - loadedMatrix.setDimensions( rows, cols ); + Matrix loadedMatrix( rows, cols ); ASSERT_NO_THROW( loadedMatrix.load( TEST_FILE_NAME ) ); -- GitLab