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

Added for[,All]Rows to lambda matrix.

parent ed7aa7cd
Loading
Loading
Loading
Loading
+168 −58
Original line number Diff line number Diff line
@@ -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 {
@@ -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
@@ -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,
@@ -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; };

@@ -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.
       *
@@ -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.
@@ -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.
       *
@@ -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).
@@ -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.
+76 −19
Original line number Diff line number Diff line
@@ -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,
@@ -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,
@@ -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,
@@ -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,
@@ -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 );
}
+8 −0
Original line number Diff line number Diff line
@@ -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;
+58 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@

#ifdef HAVE_GTEST
#include <gtest/gtest.h>
#include <TNL/Matrices/DenseMatrix.h>

template< typename Matrix >
void test_Constructors()
@@ -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()
{