Loading src/TNL/Matrices/LambdaMatrix.h +168 −58 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ #include <type_traits> #include <TNL/String.h> #include <TNL/Devices/Host.h> #include <TNL/Matrices/LambdaMatrixRowView.h> namespace TNL { namespace Matrices { Loading @@ -25,9 +26,13 @@ namespace Matrices { * * \tparam MatrixElementsLambda is a lambda function returning matrix elements values and positions. * * \tparam MatrixElementsLambda is a lambda function returning matrix elements values and positions. * * It has the following form: * * `matrixElements( Index rows, Index columns, Index rowIdx, Index localIdx, Index& columnIdx, Real& value )` * ``` * auto matrixElements = [] __cuda_callable__ ( Index rows, Index columns, Index rowIdx, Index localIdx, Index& columnIdx, Real& value ) { ... } * ``` * * where \e rows is the number of matrix rows, \e columns is the number of matrix columns, \e rowIdx is the index of matrix row being queried, * \e localIdx is the rank of the non-zero element in given row, \e columnIdx is a column index of the matrix element computed by Loading @@ -36,13 +41,15 @@ namespace Matrices { * * It has the following form: * * `rowLengths( Index rows, Index columns, Index rowIdx ) -> IndexType` * ``` * auto rowLengths = [] __cuda_callable__ ( Index rows, Index columns, Index rowIdx ) -> IndexType { ... } * ``` * * where \e rows is the number of matrix rows, \e columns is the number of matrix columns and \e rowIdx is an index of the row being queried. * * \tparam Real is a type of matrix elements values. * \tparam Device is a device on which the lambda functions will be evaluated. * \ẗparam Index is a type to be used for indexing. * \tparam Index is a type to be used for indexing. */ template< typename MatrixElementsLambda, typename CompressedRowLengthsLambda, Loading @@ -68,6 +75,26 @@ class LambdaMatrix */ using IndexType = Index; /** * \brief Type of the lambda function returning the matrix elements. */ using MatrixElementsLambdaType = MatrixElementsLambda; /** * \brief Type of the lambda function returning the number of non-zero elements in each row. */ using CompressedRowLengthsLambdaType = CompressedRowLengthsLambda; /** * \brief Type of Lambda matrix row view. */ using RowViewType = LambdaMatrixRowView< MatrixElementsLambdaType, CompressedRowLengthsLambdaType, RealType, IndexType >; /** * \brief Type of constant Lambda matrix row view. */ using ConstRowViewType = RowViewType; static constexpr bool isSymmetric() { return false; }; static constexpr bool isBinary() { return false; }; Loading Loading @@ -148,6 +175,22 @@ class LambdaMatrix __cuda_callable__ IndexType getColumns() const; /** * \brief Get reference to the lambda function returning number of non-zero elements in each row. * * \return constant reference to CompressedRowLengthsLambda. */ __cuda_callable__ const CompressedRowLengthsLambda& getCompressedRowLengthsLambda() const; /** * \brief Get reference to the lambda function returning the matrix elements values and column indexes. * * \return constant reference to MatrixElementsLambda. */ __cuda_callable__ const MatrixElementsLambda& getMatrixElementsLambda() const; /** * \brief Compute capacities of all rows. * Loading Loading @@ -185,67 +228,32 @@ class LambdaMatrix IndexType getNonzeroElementsCount() const; /** * \brief Returns value of matrix element at position given by its row and column index. * \brief Getter of simple structure for accessing given matrix row. * * \param row is a row index of the matrix element. * \param column i a column index of the matrix element. * \param rowIdx is matrix row index. * * \return value of given matrix element. */ RealType getElement( const IndexType row, const IndexType column ) const; /** * \brief Method for performing general reduction on matrix rows. * * \tparam Fetch is a type of lambda function for data fetch declared as * `fetch( IndexType rowIdx, IndexType columnIdx, RealType elementValue ) -> FetchValue`. * The return type of this lambda can be any non void. * \tparam Reduce is a type of lambda function for reduction declared as * `reduce( const FetchValue& v1, const FetchValue& v2 ) -> FetchValue`. * \tparam Keep is a type of lambda function for storing results of reduction in each row. * It is declared as `keep( const IndexType rowIdx, const double& value )`. * \tparam FetchValue is type returned by the Fetch lambda function. * * \param begin defines beginning of the range [begin,end) of rows to be processed. * \param end defines ending of the range [begin,end) of rows to be processed. * \param fetch is an instance of lambda function for data fetch. * \param reduce is an instance of lambda function for reduction. * \param keep in an instance of lambda function for storing results. * \param zero is zero of given reduction operation also known as idempotent element. * \return RowView for accessing given matrix row. * * \par Example * \include Matrices/LambdaMatrix/LambdaMatrixExample_rowsReduction.cpp * \include Matrices/SparseMatrix/LambdaMatrixExample_getRow.cpp * \par Output * \include LambdaMatrixExample_rowsReduction.out * \include LambdaMatrixExample_getRow.out * * See \ref LambdaMatrixRowView. */ template< typename Fetch, typename Reduce, typename Keep, typename FetchReal > void rowsReduction( IndexType first, IndexType last, Fetch& fetch, const Reduce& reduce, Keep& keep, const FetchReal& zero ) const; __cuda_callable__ const RowViewType getRow( const IndexType& rowIdx ) const; /** * \brief Method for performing general reduction on ALL matrix rows. * * \tparam Fetch is a type of lambda function for data fetch declared as * `fetch( IndexType rowIdx, IndexType columnIdx, RealType elementValue ) -> FetchValue`. * The return type of this lambda can be any non void. * \tparam Reduce is a type of lambda function for reduction declared as * `reduce( const FetchValue& v1, const FetchValue& v2 ) -> FetchValue`. * \tparam Keep is a type of lambda function for storing results of reduction in each row. * It is declared as `keep( const IndexType rowIdx, const double& value )`. * \tparam FetchValue is type returned by the Fetch lambda function. * \brief Returns value of matrix element at position given by its row and column index. * * \param fetch is an instance of lambda function for data fetch. * \param reduce is an instance of lambda function for reduction. * \param keep in an instance of lambda function for storing results. * \param zero is zero of given reduction operation also known as idempotent element. * \param row is a row index of the matrix element. * \param column i a column index of the matrix element. * * \par Example * \include Matrices/LambdaMatrix/LambdaMatrixExample_allRowsReduction.cpp * \par Output * \include LambdaMatrixExample_allRowsReduction.out * \return value of given matrix element. */ template< typename Fetch, typename Reduce, typename Keep, typename FetchReal > void allRowsReduction( Fetch& fetch, const Reduce& reduce, Keep& keep, const FetchReal& zero ) const; RealType getElement( const IndexType row, const IndexType column ) const; /** * \brief Method for iteration over all matrix rows for constant instances. Loading Loading @@ -285,6 +293,56 @@ class LambdaMatrix template< typename Function > void forAllElements( Function& function ) const; /** * \brief Method for parallel iteration over matrix rows from interval [ \e begin, \e end) for constant instances. * * In each row, given lambda function is performed. Each row is processed by at most one thread unlike the method * \ref LambdaMatrix::forElements where more than one thread can be mapped to each row. * * \tparam Function is type of the lambda function. * * \param begin defines beginning of the range [ \e begin,\e end ) of rows to be processed. * \param end defines ending of the range [ \e begin, \e end ) of rows to be processed. * \param function is an instance of the lambda function to be called for each row. * * ``` * auto function = [] __cuda_callable__ ( RowViewType& row ) { ... }; * ``` * * \e RowViewType represents matrix row - see \ref TNL::Matrices::LambdaMatrix::RowViewType. * * \par Example * \include Matrices/LambdaMatrix/LambdaMatrixExample_forRows.cpp * \par Output * \include LambdaMatrixExample_forRows.out */ template< typename Function > void forRows( IndexType begin, IndexType end, Function&& function ) const; /** * \brief Method for parallel iteration over all matrix rows for constant instances. * * In each row, given lambda function is performed. Each row is processed by at most one thread unlike the method * \ref LambdaMatrix::forAllElements where more than one thread can be mapped to each row. * * \tparam Function is type of the lambda function. * * \param function is an instance of the lambda function to be called for each row. * * ``` * auto function = [] __cuda_callable__ ( RowViewType& row ) { ... }; * ``` * * \e RowViewType represents matrix row - see \ref TNL::Matrices::LambdaMatrix::RowViewType. * * \par Example * \include Matrices/LambdaMatrix/LambdaMatrixExample_forRows.cpp * \par Output * \include LambdaMatrixExample_forRows.out */ template< typename Function > void forAllRows( Function&& function ) const; /** * \brief Method for sequential iteration over all matrix rows for constant instances. * Loading @@ -300,7 +358,7 @@ class LambdaMatrix * \param function is an instance of the lambda function to be called in each row. */ template< typename Function > void sequentialForRows( IndexType begin, IndexType end, Function& function ) const; void sequentialForRows( IndexType begin, IndexType end, Function&& function ) const; /** * \brief This method calls \e sequentialForRows for all matrix rows (for constant instances). Loading @@ -311,7 +369,59 @@ class LambdaMatrix * \param function is an instance of the lambda function to be called in each row. */ template< typename Function > void sequentialForAllRows( Function& function ) const; void sequentialForAllRows( Function&& function ) const; /** * \brief Method for performing general reduction on matrix rows. * * \tparam Fetch is a type of lambda function for data fetch declared as * `fetch( IndexType rowIdx, IndexType columnIdx, RealType elementValue ) -> FetchValue`. * The return type of this lambda can be any non void. * \tparam Reduce is a type of lambda function for reduction declared as * `reduce( const FetchValue& v1, const FetchValue& v2 ) -> FetchValue`. * \tparam Keep is a type of lambda function for storing results of reduction in each row. * It is declared as `keep( const IndexType rowIdx, const double& value )`. * \tparam FetchValue is type returned by the Fetch lambda function. * * \param begin defines beginning of the range [begin,end) of rows to be processed. * \param end defines ending of the range [begin,end) of rows to be processed. * \param fetch is an instance of lambda function for data fetch. * \param reduce is an instance of lambda function for reduction. * \param keep in an instance of lambda function for storing results. * \param zero is zero of given reduction operation also known as idempotent element. * * \par Example * \include Matrices/LambdaMatrix/LambdaMatrixExample_rowsReduction.cpp * \par Output * \include LambdaMatrixExample_rowsReduction.out */ template< typename Fetch, typename Reduce, typename Keep, typename FetchReal > void rowsReduction( IndexType first, IndexType last, Fetch& fetch, const Reduce& reduce, Keep& keep, const FetchReal& zero ) const; /** * \brief Method for performing general reduction on ALL matrix rows. * * \tparam Fetch is a type of lambda function for data fetch declared as * `fetch( IndexType rowIdx, IndexType columnIdx, RealType elementValue ) -> FetchValue`. * The return type of this lambda can be any non void. * \tparam Reduce is a type of lambda function for reduction declared as * `reduce( const FetchValue& v1, const FetchValue& v2 ) -> FetchValue`. * \tparam Keep is a type of lambda function for storing results of reduction in each row. * It is declared as `keep( const IndexType rowIdx, const double& value )`. * \tparam FetchValue is type returned by the Fetch lambda function. * * \param fetch is an instance of lambda function for data fetch. * \param reduce is an instance of lambda function for reduction. * \param keep in an instance of lambda function for storing results. * \param zero is zero of given reduction operation also known as idempotent element. * * \par Example * \include Matrices/LambdaMatrix/LambdaMatrixExample_allRowsReduction.cpp * \par Output * \include LambdaMatrixExample_allRowsReduction.out */ template< typename Fetch, typename Reduce, typename Keep, typename FetchReal > void allRowsReduction( Fetch& fetch, const Reduce& reduce, Keep& keep, const FetchReal& zero ) const; /** * \brief Computes product of matrix and vector. Loading src/TNL/Matrices/LambdaMatrix.hpp +76 −19 Original line number Diff line number Diff line Loading @@ -87,6 +87,32 @@ getColumns() const return this->columns; } template< typename MatrixElementsLambda, typename CompressedRowLengthsLambda, typename Real, typename Device, typename Index > __cuda_callable__ const CompressedRowLengthsLambda& LambdaMatrix< MatrixElementsLambda, CompressedRowLengthsLambda, Real, Device, Index >:: getCompressedRowLengthsLambda() const { return this->compressedRowLengthsLambda; } template< typename MatrixElementsLambda, typename CompressedRowLengthsLambda, typename Real, typename Device, typename Index > __cuda_callable__ const MatrixElementsLambda& LambdaMatrix< MatrixElementsLambda, CompressedRowLengthsLambda, Real, Device, Index >:: getMatrixElementsLambda() const { return this->matrixElementsLambda; } template< typename MatrixElementsLambda, typename CompressedRowLengthsLambda, typename Real, Loading Loading @@ -171,6 +197,23 @@ getElement( const IndexType row, return valueView.getElement( 0 ); } template< typename MatrixElementsLambda, typename CompressedRowLengthsLambda, typename Real, typename Device, typename Index > __cuda_callable__ auto LambdaMatrix< MatrixElementsLambda, CompressedRowLengthsLambda, Real, Device, Index >:: getRow( const IndexType& rowIdx ) const -> const RowViewType { return RowViewType( this->getMatrixElementsLambda(), this->getCompressedRowLengthsLambda(), this->getRows(), this->getColumns(), rowIdx ); } template< typename MatrixElementsLambda, typename CompressedRowLengthsLambda, typename Real, Loading Loading @@ -298,23 +341,37 @@ LambdaMatrix< MatrixElementsLambda, CompressedRowLengthsLambda, Real, Device, In forAllElements( Function& function ) const { forElements( 0, this->getRows(), function ); /*const IndexType rows = this->getRows(); const IndexType columns = this->getColumns(); auto rowLengths = this->compressedRowLengthsLambda; auto matrixElements = this->matrixElementsLambda; auto processRow = [=] __cuda_callable__ ( IndexType rowIdx ) mutable { const IndexType rowLength = rowLengths( rows, columns, rowIdx ); bool compute( true ); for( IndexType localIdx = 0; localIdx < rowLength && compute; localIdx++ ) { IndexType elementColumn( 0 ); RealType elementValue( 0.0 ); matrixElements( rows, columns, rowIdx, localIdx, elementColumn, elementValue ); if( elementValue != 0.0 ) function( rowIdx, localIdx, elementColumn, elementValue, compute ); } template< typename MatrixElementsLambda, typename CompressedRowLengthsLambda, typename Real, typename Device, typename Index > template< typename Function > void LambdaMatrix< MatrixElementsLambda, CompressedRowLengthsLambda, Real, Device, Index >:: forRows( IndexType begin, IndexType end, Function&& function ) const { auto view = *this; auto f = [=] __cuda_callable__ ( const IndexType rowIdx ) mutable { auto rowView = view.getRow( rowIdx ); function( rowView ); }; Algorithms::ParallelFor< DeviceType >::exec( 0, this->getRows(), processRow );*/ TNL::Algorithms::ParallelFor< DeviceType >::exec( begin, end, f ); } template< typename MatrixElementsLambda, typename CompressedRowLengthsLambda, typename Real, typename Device, typename Index > template< typename Function > void LambdaMatrix< MatrixElementsLambda, CompressedRowLengthsLambda, Real, Device, Index >:: forAllRows( Function&& function ) const { this->forRows( 0, this->getRows(), function ); } template< typename MatrixElementsLambda, Loading @@ -325,10 +382,10 @@ template< typename MatrixElementsLambda, template< typename Function > void LambdaMatrix< MatrixElementsLambda, CompressedRowLengthsLambda, Real, Device, Index >:: sequentialForRows( IndexType begin, IndexType end, Function& function ) const sequentialForRows( IndexType begin, IndexType end, Function&& function ) const { for( IndexType row = begin; row < end; row ++ ) this->forElements( row, row + 1, function ); this->forRows( row, row + 1, function ); } template< typename MatrixElementsLambda, Loading @@ -339,7 +396,7 @@ template< typename MatrixElementsLambda, template< typename Function > void LambdaMatrix< MatrixElementsLambda, CompressedRowLengthsLambda, Real, Device, Index >:: sequentialForAllRows( Function& function ) const sequentialForAllRows( Function&& function ) const { sequentialForRows( 0, this->getRows(), function ); } Loading src/UnitTests/Matrices/LambdaMatrixTest.h +8 −0 Original line number Diff line number Diff line Loading @@ -89,6 +89,14 @@ TYPED_TEST( LambdaMatrixTest, getElementTest ) test_GetElement< LambdaMatrixParametersType >(); } TYPED_TEST( LambdaMatrixTest, getRowTest ) { using LambdaMatrixParametersType = typename TestFixture::LambdaMatrixType; test_GetRow< LambdaMatrixParametersType >(); } TYPED_TEST( LambdaMatrixTest, vectorProductTest ) { using LambdaMatrixParametersType = typename TestFixture::LambdaMatrixType; Loading src/UnitTests/Matrices/LambdaMatrixTest.hpp +58 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ #ifdef HAVE_GTEST #include <gtest/gtest.h> #include <TNL/Matrices/DenseMatrix.h> template< typename Matrix > void test_Constructors() Loading Loading @@ -161,6 +162,63 @@ void test_GetElement() EXPECT_EQ( m.getElement( 4, 4 ), 1.0 ); } template< typename Matrix > void test_GetRow() { using RealType = typename Matrix::RealType; using DeviceType = typename Matrix::DeviceType; using IndexType = typename Matrix::IndexType; ///// // Prepare lambda matrix of the following form: // // / 1 0 0 0 0 \ // | -2 1 -2 0 0 | // | 0 -2 1 -2 0 | // | 0 0 -2 1 -2 | // | 0 0 0 -2 1 | // \ 0 0 0 0 1 / IndexType size = 5; auto rowLengths = [=] __cuda_callable__ ( const IndexType rows, const IndexType columns, const IndexType rowIdx ) -> IndexType { if( rowIdx == 0 || rowIdx == size - 1 ) return 1; return 3; }; auto matrixElements = [=] __cuda_callable__ ( const IndexType rows, const IndexType columns, const IndexType rowIdx, const IndexType localIdx, IndexType& columnIdx, RealType& value ) { if( rowIdx == 0 || rowIdx == size -1 ) { columnIdx = rowIdx; value = 1.0; } else { columnIdx = rowIdx + localIdx - 1; value = ( columnIdx == rowIdx ) ? -2.0 : 1.0; } }; using MatrixType = decltype( TNL::Matrices::LambdaMatrixFactory< RealType, DeviceType, IndexType >::create( matrixElements, rowLengths ) ); MatrixType m( size, size, matrixElements, rowLengths ); TNL::Matrices::DenseMatrix< RealType, DeviceType, IndexType > denseMatrix( size, size ); denseMatrix.setValue( 0.0 ); auto dense_view = denseMatrix.getView(); auto f = [=] __cuda_callable__ ( const typename MatrixType::RowViewType& row ) mutable { auto dense_row = dense_view.getRow( row.getRowIndex() ); for( IndexType localIdx = 0; localIdx < row.getSize(); localIdx++ ) dense_row.setElement( row.getColumnIndex( localIdx ), row.getValue( localIdx ) ); }; m.forAllRows( f ); for( IndexType row = 0; row < size; row++ ) for( IndexType column = 0; column < size; column++ ) EXPECT_EQ( m.getElement( row, column ), denseMatrix.getElement( row, column ) ); } template< typename Matrix > void test_VectorProduct() { Loading Loading
src/TNL/Matrices/LambdaMatrix.h +168 −58 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ #include <type_traits> #include <TNL/String.h> #include <TNL/Devices/Host.h> #include <TNL/Matrices/LambdaMatrixRowView.h> namespace TNL { namespace Matrices { Loading @@ -25,9 +26,13 @@ namespace Matrices { * * \tparam MatrixElementsLambda is a lambda function returning matrix elements values and positions. * * \tparam MatrixElementsLambda is a lambda function returning matrix elements values and positions. * * It has the following form: * * `matrixElements( Index rows, Index columns, Index rowIdx, Index localIdx, Index& columnIdx, Real& value )` * ``` * auto matrixElements = [] __cuda_callable__ ( Index rows, Index columns, Index rowIdx, Index localIdx, Index& columnIdx, Real& value ) { ... } * ``` * * where \e rows is the number of matrix rows, \e columns is the number of matrix columns, \e rowIdx is the index of matrix row being queried, * \e localIdx is the rank of the non-zero element in given row, \e columnIdx is a column index of the matrix element computed by Loading @@ -36,13 +41,15 @@ namespace Matrices { * * It has the following form: * * `rowLengths( Index rows, Index columns, Index rowIdx ) -> IndexType` * ``` * auto rowLengths = [] __cuda_callable__ ( Index rows, Index columns, Index rowIdx ) -> IndexType { ... } * ``` * * where \e rows is the number of matrix rows, \e columns is the number of matrix columns and \e rowIdx is an index of the row being queried. * * \tparam Real is a type of matrix elements values. * \tparam Device is a device on which the lambda functions will be evaluated. * \ẗparam Index is a type to be used for indexing. * \tparam Index is a type to be used for indexing. */ template< typename MatrixElementsLambda, typename CompressedRowLengthsLambda, Loading @@ -68,6 +75,26 @@ class LambdaMatrix */ using IndexType = Index; /** * \brief Type of the lambda function returning the matrix elements. */ using MatrixElementsLambdaType = MatrixElementsLambda; /** * \brief Type of the lambda function returning the number of non-zero elements in each row. */ using CompressedRowLengthsLambdaType = CompressedRowLengthsLambda; /** * \brief Type of Lambda matrix row view. */ using RowViewType = LambdaMatrixRowView< MatrixElementsLambdaType, CompressedRowLengthsLambdaType, RealType, IndexType >; /** * \brief Type of constant Lambda matrix row view. */ using ConstRowViewType = RowViewType; static constexpr bool isSymmetric() { return false; }; static constexpr bool isBinary() { return false; }; Loading Loading @@ -148,6 +175,22 @@ class LambdaMatrix __cuda_callable__ IndexType getColumns() const; /** * \brief Get reference to the lambda function returning number of non-zero elements in each row. * * \return constant reference to CompressedRowLengthsLambda. */ __cuda_callable__ const CompressedRowLengthsLambda& getCompressedRowLengthsLambda() const; /** * \brief Get reference to the lambda function returning the matrix elements values and column indexes. * * \return constant reference to MatrixElementsLambda. */ __cuda_callable__ const MatrixElementsLambda& getMatrixElementsLambda() const; /** * \brief Compute capacities of all rows. * Loading Loading @@ -185,67 +228,32 @@ class LambdaMatrix IndexType getNonzeroElementsCount() const; /** * \brief Returns value of matrix element at position given by its row and column index. * \brief Getter of simple structure for accessing given matrix row. * * \param row is a row index of the matrix element. * \param column i a column index of the matrix element. * \param rowIdx is matrix row index. * * \return value of given matrix element. */ RealType getElement( const IndexType row, const IndexType column ) const; /** * \brief Method for performing general reduction on matrix rows. * * \tparam Fetch is a type of lambda function for data fetch declared as * `fetch( IndexType rowIdx, IndexType columnIdx, RealType elementValue ) -> FetchValue`. * The return type of this lambda can be any non void. * \tparam Reduce is a type of lambda function for reduction declared as * `reduce( const FetchValue& v1, const FetchValue& v2 ) -> FetchValue`. * \tparam Keep is a type of lambda function for storing results of reduction in each row. * It is declared as `keep( const IndexType rowIdx, const double& value )`. * \tparam FetchValue is type returned by the Fetch lambda function. * * \param begin defines beginning of the range [begin,end) of rows to be processed. * \param end defines ending of the range [begin,end) of rows to be processed. * \param fetch is an instance of lambda function for data fetch. * \param reduce is an instance of lambda function for reduction. * \param keep in an instance of lambda function for storing results. * \param zero is zero of given reduction operation also known as idempotent element. * \return RowView for accessing given matrix row. * * \par Example * \include Matrices/LambdaMatrix/LambdaMatrixExample_rowsReduction.cpp * \include Matrices/SparseMatrix/LambdaMatrixExample_getRow.cpp * \par Output * \include LambdaMatrixExample_rowsReduction.out * \include LambdaMatrixExample_getRow.out * * See \ref LambdaMatrixRowView. */ template< typename Fetch, typename Reduce, typename Keep, typename FetchReal > void rowsReduction( IndexType first, IndexType last, Fetch& fetch, const Reduce& reduce, Keep& keep, const FetchReal& zero ) const; __cuda_callable__ const RowViewType getRow( const IndexType& rowIdx ) const; /** * \brief Method for performing general reduction on ALL matrix rows. * * \tparam Fetch is a type of lambda function for data fetch declared as * `fetch( IndexType rowIdx, IndexType columnIdx, RealType elementValue ) -> FetchValue`. * The return type of this lambda can be any non void. * \tparam Reduce is a type of lambda function for reduction declared as * `reduce( const FetchValue& v1, const FetchValue& v2 ) -> FetchValue`. * \tparam Keep is a type of lambda function for storing results of reduction in each row. * It is declared as `keep( const IndexType rowIdx, const double& value )`. * \tparam FetchValue is type returned by the Fetch lambda function. * \brief Returns value of matrix element at position given by its row and column index. * * \param fetch is an instance of lambda function for data fetch. * \param reduce is an instance of lambda function for reduction. * \param keep in an instance of lambda function for storing results. * \param zero is zero of given reduction operation also known as idempotent element. * \param row is a row index of the matrix element. * \param column i a column index of the matrix element. * * \par Example * \include Matrices/LambdaMatrix/LambdaMatrixExample_allRowsReduction.cpp * \par Output * \include LambdaMatrixExample_allRowsReduction.out * \return value of given matrix element. */ template< typename Fetch, typename Reduce, typename Keep, typename FetchReal > void allRowsReduction( Fetch& fetch, const Reduce& reduce, Keep& keep, const FetchReal& zero ) const; RealType getElement( const IndexType row, const IndexType column ) const; /** * \brief Method for iteration over all matrix rows for constant instances. Loading Loading @@ -285,6 +293,56 @@ class LambdaMatrix template< typename Function > void forAllElements( Function& function ) const; /** * \brief Method for parallel iteration over matrix rows from interval [ \e begin, \e end) for constant instances. * * In each row, given lambda function is performed. Each row is processed by at most one thread unlike the method * \ref LambdaMatrix::forElements where more than one thread can be mapped to each row. * * \tparam Function is type of the lambda function. * * \param begin defines beginning of the range [ \e begin,\e end ) of rows to be processed. * \param end defines ending of the range [ \e begin, \e end ) of rows to be processed. * \param function is an instance of the lambda function to be called for each row. * * ``` * auto function = [] __cuda_callable__ ( RowViewType& row ) { ... }; * ``` * * \e RowViewType represents matrix row - see \ref TNL::Matrices::LambdaMatrix::RowViewType. * * \par Example * \include Matrices/LambdaMatrix/LambdaMatrixExample_forRows.cpp * \par Output * \include LambdaMatrixExample_forRows.out */ template< typename Function > void forRows( IndexType begin, IndexType end, Function&& function ) const; /** * \brief Method for parallel iteration over all matrix rows for constant instances. * * In each row, given lambda function is performed. Each row is processed by at most one thread unlike the method * \ref LambdaMatrix::forAllElements where more than one thread can be mapped to each row. * * \tparam Function is type of the lambda function. * * \param function is an instance of the lambda function to be called for each row. * * ``` * auto function = [] __cuda_callable__ ( RowViewType& row ) { ... }; * ``` * * \e RowViewType represents matrix row - see \ref TNL::Matrices::LambdaMatrix::RowViewType. * * \par Example * \include Matrices/LambdaMatrix/LambdaMatrixExample_forRows.cpp * \par Output * \include LambdaMatrixExample_forRows.out */ template< typename Function > void forAllRows( Function&& function ) const; /** * \brief Method for sequential iteration over all matrix rows for constant instances. * Loading @@ -300,7 +358,7 @@ class LambdaMatrix * \param function is an instance of the lambda function to be called in each row. */ template< typename Function > void sequentialForRows( IndexType begin, IndexType end, Function& function ) const; void sequentialForRows( IndexType begin, IndexType end, Function&& function ) const; /** * \brief This method calls \e sequentialForRows for all matrix rows (for constant instances). Loading @@ -311,7 +369,59 @@ class LambdaMatrix * \param function is an instance of the lambda function to be called in each row. */ template< typename Function > void sequentialForAllRows( Function& function ) const; void sequentialForAllRows( Function&& function ) const; /** * \brief Method for performing general reduction on matrix rows. * * \tparam Fetch is a type of lambda function for data fetch declared as * `fetch( IndexType rowIdx, IndexType columnIdx, RealType elementValue ) -> FetchValue`. * The return type of this lambda can be any non void. * \tparam Reduce is a type of lambda function for reduction declared as * `reduce( const FetchValue& v1, const FetchValue& v2 ) -> FetchValue`. * \tparam Keep is a type of lambda function for storing results of reduction in each row. * It is declared as `keep( const IndexType rowIdx, const double& value )`. * \tparam FetchValue is type returned by the Fetch lambda function. * * \param begin defines beginning of the range [begin,end) of rows to be processed. * \param end defines ending of the range [begin,end) of rows to be processed. * \param fetch is an instance of lambda function for data fetch. * \param reduce is an instance of lambda function for reduction. * \param keep in an instance of lambda function for storing results. * \param zero is zero of given reduction operation also known as idempotent element. * * \par Example * \include Matrices/LambdaMatrix/LambdaMatrixExample_rowsReduction.cpp * \par Output * \include LambdaMatrixExample_rowsReduction.out */ template< typename Fetch, typename Reduce, typename Keep, typename FetchReal > void rowsReduction( IndexType first, IndexType last, Fetch& fetch, const Reduce& reduce, Keep& keep, const FetchReal& zero ) const; /** * \brief Method for performing general reduction on ALL matrix rows. * * \tparam Fetch is a type of lambda function for data fetch declared as * `fetch( IndexType rowIdx, IndexType columnIdx, RealType elementValue ) -> FetchValue`. * The return type of this lambda can be any non void. * \tparam Reduce is a type of lambda function for reduction declared as * `reduce( const FetchValue& v1, const FetchValue& v2 ) -> FetchValue`. * \tparam Keep is a type of lambda function for storing results of reduction in each row. * It is declared as `keep( const IndexType rowIdx, const double& value )`. * \tparam FetchValue is type returned by the Fetch lambda function. * * \param fetch is an instance of lambda function for data fetch. * \param reduce is an instance of lambda function for reduction. * \param keep in an instance of lambda function for storing results. * \param zero is zero of given reduction operation also known as idempotent element. * * \par Example * \include Matrices/LambdaMatrix/LambdaMatrixExample_allRowsReduction.cpp * \par Output * \include LambdaMatrixExample_allRowsReduction.out */ template< typename Fetch, typename Reduce, typename Keep, typename FetchReal > void allRowsReduction( Fetch& fetch, const Reduce& reduce, Keep& keep, const FetchReal& zero ) const; /** * \brief Computes product of matrix and vector. Loading
src/TNL/Matrices/LambdaMatrix.hpp +76 −19 Original line number Diff line number Diff line Loading @@ -87,6 +87,32 @@ getColumns() const return this->columns; } template< typename MatrixElementsLambda, typename CompressedRowLengthsLambda, typename Real, typename Device, typename Index > __cuda_callable__ const CompressedRowLengthsLambda& LambdaMatrix< MatrixElementsLambda, CompressedRowLengthsLambda, Real, Device, Index >:: getCompressedRowLengthsLambda() const { return this->compressedRowLengthsLambda; } template< typename MatrixElementsLambda, typename CompressedRowLengthsLambda, typename Real, typename Device, typename Index > __cuda_callable__ const MatrixElementsLambda& LambdaMatrix< MatrixElementsLambda, CompressedRowLengthsLambda, Real, Device, Index >:: getMatrixElementsLambda() const { return this->matrixElementsLambda; } template< typename MatrixElementsLambda, typename CompressedRowLengthsLambda, typename Real, Loading Loading @@ -171,6 +197,23 @@ getElement( const IndexType row, return valueView.getElement( 0 ); } template< typename MatrixElementsLambda, typename CompressedRowLengthsLambda, typename Real, typename Device, typename Index > __cuda_callable__ auto LambdaMatrix< MatrixElementsLambda, CompressedRowLengthsLambda, Real, Device, Index >:: getRow( const IndexType& rowIdx ) const -> const RowViewType { return RowViewType( this->getMatrixElementsLambda(), this->getCompressedRowLengthsLambda(), this->getRows(), this->getColumns(), rowIdx ); } template< typename MatrixElementsLambda, typename CompressedRowLengthsLambda, typename Real, Loading Loading @@ -298,23 +341,37 @@ LambdaMatrix< MatrixElementsLambda, CompressedRowLengthsLambda, Real, Device, In forAllElements( Function& function ) const { forElements( 0, this->getRows(), function ); /*const IndexType rows = this->getRows(); const IndexType columns = this->getColumns(); auto rowLengths = this->compressedRowLengthsLambda; auto matrixElements = this->matrixElementsLambda; auto processRow = [=] __cuda_callable__ ( IndexType rowIdx ) mutable { const IndexType rowLength = rowLengths( rows, columns, rowIdx ); bool compute( true ); for( IndexType localIdx = 0; localIdx < rowLength && compute; localIdx++ ) { IndexType elementColumn( 0 ); RealType elementValue( 0.0 ); matrixElements( rows, columns, rowIdx, localIdx, elementColumn, elementValue ); if( elementValue != 0.0 ) function( rowIdx, localIdx, elementColumn, elementValue, compute ); } template< typename MatrixElementsLambda, typename CompressedRowLengthsLambda, typename Real, typename Device, typename Index > template< typename Function > void LambdaMatrix< MatrixElementsLambda, CompressedRowLengthsLambda, Real, Device, Index >:: forRows( IndexType begin, IndexType end, Function&& function ) const { auto view = *this; auto f = [=] __cuda_callable__ ( const IndexType rowIdx ) mutable { auto rowView = view.getRow( rowIdx ); function( rowView ); }; Algorithms::ParallelFor< DeviceType >::exec( 0, this->getRows(), processRow );*/ TNL::Algorithms::ParallelFor< DeviceType >::exec( begin, end, f ); } template< typename MatrixElementsLambda, typename CompressedRowLengthsLambda, typename Real, typename Device, typename Index > template< typename Function > void LambdaMatrix< MatrixElementsLambda, CompressedRowLengthsLambda, Real, Device, Index >:: forAllRows( Function&& function ) const { this->forRows( 0, this->getRows(), function ); } template< typename MatrixElementsLambda, Loading @@ -325,10 +382,10 @@ template< typename MatrixElementsLambda, template< typename Function > void LambdaMatrix< MatrixElementsLambda, CompressedRowLengthsLambda, Real, Device, Index >:: sequentialForRows( IndexType begin, IndexType end, Function& function ) const sequentialForRows( IndexType begin, IndexType end, Function&& function ) const { for( IndexType row = begin; row < end; row ++ ) this->forElements( row, row + 1, function ); this->forRows( row, row + 1, function ); } template< typename MatrixElementsLambda, Loading @@ -339,7 +396,7 @@ template< typename MatrixElementsLambda, template< typename Function > void LambdaMatrix< MatrixElementsLambda, CompressedRowLengthsLambda, Real, Device, Index >:: sequentialForAllRows( Function& function ) const sequentialForAllRows( Function&& function ) const { sequentialForRows( 0, this->getRows(), function ); } Loading
src/UnitTests/Matrices/LambdaMatrixTest.h +8 −0 Original line number Diff line number Diff line Loading @@ -89,6 +89,14 @@ TYPED_TEST( LambdaMatrixTest, getElementTest ) test_GetElement< LambdaMatrixParametersType >(); } TYPED_TEST( LambdaMatrixTest, getRowTest ) { using LambdaMatrixParametersType = typename TestFixture::LambdaMatrixType; test_GetRow< LambdaMatrixParametersType >(); } TYPED_TEST( LambdaMatrixTest, vectorProductTest ) { using LambdaMatrixParametersType = typename TestFixture::LambdaMatrixType; Loading
src/UnitTests/Matrices/LambdaMatrixTest.hpp +58 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ #ifdef HAVE_GTEST #include <gtest/gtest.h> #include <TNL/Matrices/DenseMatrix.h> template< typename Matrix > void test_Constructors() Loading Loading @@ -161,6 +162,63 @@ void test_GetElement() EXPECT_EQ( m.getElement( 4, 4 ), 1.0 ); } template< typename Matrix > void test_GetRow() { using RealType = typename Matrix::RealType; using DeviceType = typename Matrix::DeviceType; using IndexType = typename Matrix::IndexType; ///// // Prepare lambda matrix of the following form: // // / 1 0 0 0 0 \ // | -2 1 -2 0 0 | // | 0 -2 1 -2 0 | // | 0 0 -2 1 -2 | // | 0 0 0 -2 1 | // \ 0 0 0 0 1 / IndexType size = 5; auto rowLengths = [=] __cuda_callable__ ( const IndexType rows, const IndexType columns, const IndexType rowIdx ) -> IndexType { if( rowIdx == 0 || rowIdx == size - 1 ) return 1; return 3; }; auto matrixElements = [=] __cuda_callable__ ( const IndexType rows, const IndexType columns, const IndexType rowIdx, const IndexType localIdx, IndexType& columnIdx, RealType& value ) { if( rowIdx == 0 || rowIdx == size -1 ) { columnIdx = rowIdx; value = 1.0; } else { columnIdx = rowIdx + localIdx - 1; value = ( columnIdx == rowIdx ) ? -2.0 : 1.0; } }; using MatrixType = decltype( TNL::Matrices::LambdaMatrixFactory< RealType, DeviceType, IndexType >::create( matrixElements, rowLengths ) ); MatrixType m( size, size, matrixElements, rowLengths ); TNL::Matrices::DenseMatrix< RealType, DeviceType, IndexType > denseMatrix( size, size ); denseMatrix.setValue( 0.0 ); auto dense_view = denseMatrix.getView(); auto f = [=] __cuda_callable__ ( const typename MatrixType::RowViewType& row ) mutable { auto dense_row = dense_view.getRow( row.getRowIndex() ); for( IndexType localIdx = 0; localIdx < row.getSize(); localIdx++ ) dense_row.setElement( row.getColumnIndex( localIdx ), row.getValue( localIdx ) ); }; m.forAllRows( f ); for( IndexType row = 0; row < size; row++ ) for( IndexType column = 0; column < size; column++ ) EXPECT_EQ( m.getElement( row, column ), denseMatrix.getElement( row, column ) ); } template< typename Matrix > void test_VectorProduct() { Loading