DenseMatrix.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_SMP_HPX_DENSEMATRIX_H_
36 #define _BLAZE_MATH_SMP_HPX_DENSEMATRIX_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <hpx/include/parallel_for_loop.hpp>
44 #include <blaze/math/Aliases.h>
63 #include <blaze/system/SMP.h>
65 #include <blaze/util/Assert.h>
66 #include <blaze/util/EnableIf.h>
69 #include <blaze/util/Types.h>
70 
71 
72 namespace blaze {
73 
74 //=================================================================================================
75 //
76 // HPX-BASED ASSIGNMENT KERNELS
77 //
78 //=================================================================================================
79 
80 //*************************************************************************************************
97 template< typename MT1 // Type of the left-hand side dense matrix
98  , bool SO1 // Storage order of the left-hand side dense matrix
99  , typename MT2 // Type of the right-hand side dense matrix
100  , bool SO2 // Storage order of the right-hand side dense matrix
101  , typename OP > // Type of the assignment operation
102 void hpxAssign( DenseMatrix<MT1,SO1>& lhs, const DenseMatrix<MT2,SO2>& rhs, OP op )
103 {
104  using hpx::parallel::for_loop;
105  using hpx::parallel::execution::par;
106 
108 
109  using ET1 = ElementType_t<MT1>;
110  using ET2 = ElementType_t<MT2>;
111 
112  constexpr bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSIMDCombinable_v<ET1,ET2> );
113  constexpr size_t SIMDSIZE( SIMDTrait< ElementType_t<MT1> >::size );
114 
115  const bool lhsAligned( (~lhs).isAligned() );
116  const bool rhsAligned( (~rhs).isAligned() );
117 
118  const size_t threads ( getNumThreads() );
119  const ThreadMapping threadmap( createThreadMapping( threads, ~rhs ) );
120 
121  const size_t addon1 ( ( ( (~rhs).rows() % threadmap.first ) != 0UL )? 1UL : 0UL );
122  const size_t equalShare1( (~rhs).rows() / threadmap.first + addon1 );
123  const size_t rest1 ( equalShare1 & ( SIMDSIZE - 1UL ) );
124  const size_t rowsPerThread( ( simdEnabled && rest1 )?( equalShare1 - rest1 + SIMDSIZE ):( equalShare1 ) );
125 
126  const size_t addon2 ( ( ( (~rhs).columns() % threadmap.second ) != 0UL )? 1UL : 0UL );
127  const size_t equalShare2( (~rhs).columns() / threadmap.second + addon2 );
128  const size_t rest2 ( equalShare2 & ( SIMDSIZE - 1UL ) );
129  const size_t colsPerThread( ( simdEnabled && rest2 )?( equalShare2 - rest2 + SIMDSIZE ):( equalShare2 ) );
130 
131  for_loop( par, size_t(0), threads, [&](int i)
132  {
133  const size_t row ( ( i / threadmap.second ) * rowsPerThread );
134  const size_t column( ( i % threadmap.second ) * colsPerThread );
135 
136  if( row >= (~rhs).rows() || column >= (~rhs).columns() )
137  return;
138 
139  const size_t m( min( rowsPerThread, (~rhs).rows() - row ) );
140  const size_t n( min( colsPerThread, (~rhs).columns() - column ) );
141 
142  if( simdEnabled && lhsAligned && rhsAligned ) {
143  auto target( submatrix<aligned>( ~lhs, row, column, m, n ) );
144  const auto source( submatrix<aligned>( ~rhs, row, column, m, n ) );
145  op( target, source );
146  }
147  else if( simdEnabled && lhsAligned ) {
148  auto target( submatrix<aligned>( ~lhs, row, column, m, n ) );
149  const auto source( submatrix<unaligned>( ~rhs, row, column, m, n ) );
150  op( target, source );
151  }
152  else if( simdEnabled && rhsAligned ) {
153  auto target( submatrix<unaligned>( ~lhs, row, column, m, n ) );
154  const auto source( submatrix<aligned>( ~rhs, row, column, m, n ) );
155  op( target, source );
156  }
157  else {
158  auto target( submatrix<unaligned>( ~lhs, row, column, m, n ) );
159  const auto source( submatrix<unaligned>( ~rhs, row, column, m, n ) );
160  op( target, source );
161  }
162  } );
163 }
165 //*************************************************************************************************
166 
167 
168 //*************************************************************************************************
185 template< typename MT1 // Type of the left-hand side dense matrix
186  , bool SO1 // Storage order of the left-hand side dense matrix
187  , typename MT2 // Type of the right-hand side sparse matrix
188  , bool SO2 // Storage order of the right-hand side sparse matrix
189  , typename OP > // Type of the assignment operation
190 void hpxAssign( DenseMatrix<MT1,SO1>& lhs, const SparseMatrix<MT2,SO2>& rhs, OP op )
191 {
192  using hpx::parallel::for_loop;
193  using hpx::parallel::execution::par;
194 
196 
197  const size_t threads ( getNumThreads() );
198  const ThreadMapping threadmap( createThreadMapping( threads, ~rhs ) );
199 
200  const size_t addon1 ( ( ( (~rhs).rows() % threadmap.first ) != 0UL )? 1UL : 0UL );
201  const size_t rowsPerThread( (~rhs).rows() / threadmap.first + addon1 );
202 
203  const size_t addon2 ( ( ( (~rhs).columns() % threadmap.second ) != 0UL )? 1UL : 0UL );
204  const size_t colsPerThread( (~rhs).columns() / threadmap.second + addon2 );
205 
206  for_loop( par, size_t(0), threads, [&](int i)
207  {
208  const size_t row ( ( i / threadmap.second ) * rowsPerThread );
209  const size_t column( ( i % threadmap.second ) * colsPerThread );
210 
211  if( row >= (~rhs).rows() || column >= (~rhs).columns() )
212  return;
213 
214  const size_t m( min( rowsPerThread, (~lhs).rows() - row ) );
215  const size_t n( min( colsPerThread, (~lhs).columns() - column ) );
216 
217  auto target( submatrix<unaligned>( ~lhs, row, column, m, n ) );
218  const auto source( submatrix<unaligned>( ~rhs, row, column, m, n ) );
219  op( target, source );
220  } );
221 }
223 //*************************************************************************************************
224 
225 
226 
227 
228 //=================================================================================================
229 //
230 // PLAIN ASSIGNMENT
231 //
232 //=================================================================================================
233 
234 //*************************************************************************************************
252 template< typename MT1 // Type of the left-hand side dense matrix
253  , bool SO1 // Storage order of the left-hand side dense matrix
254  , typename MT2 // Type of the right-hand side matrix
255  , bool SO2 > // Storage order of the right-hand side matrix
256 inline auto smpAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
257  -> EnableIf_t< IsDenseMatrix_v<MT1> && ( !IsSMPAssignable_v<MT1> || !IsSMPAssignable_v<MT2> ) >
258 {
260 
261  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
262  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
263 
264  assign( ~lhs, ~rhs );
265 }
267 //*************************************************************************************************
268 
269 
270 //*************************************************************************************************
288 template< typename MT1 // Type of the left-hand side dense matrix
289  , bool SO1 // Storage order of the left-hand side dense matrix
290  , typename MT2 // Type of the right-hand side matrix
291  , bool SO2 > // Storage order of the right-hand side matrix
292 inline auto smpAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
293  -> EnableIf_t< IsDenseMatrix_v<MT1> && IsSMPAssignable_v<MT1> && IsSMPAssignable_v<MT2> >
294 {
296 
297  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT1> );
298  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT2> );
299 
300  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
301  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
302 
303  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
304  assign( ~lhs, ~rhs );
305  }
306  else {
307  hpxAssign( ~lhs, ~rhs, Assign() );
308  }
309 }
311 //*************************************************************************************************
312 
313 
314 
315 
316 //=================================================================================================
317 //
318 // ADDITION ASSIGNMENT
319 //
320 //=================================================================================================
321 
322 //*************************************************************************************************
340 template< typename MT1 // Type of the left-hand side dense matrix
341  , bool SO1 // Storage order of the left-hand side dense matrix
342  , typename MT2 // Type of the right-hand side matrix
343  , bool SO2 > // Storage order of the right-hand side matrix
344 inline auto smpAddAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
345  -> EnableIf_t< IsDenseMatrix_v<MT1> && ( !IsSMPAssignable_v<MT1> || !IsSMPAssignable_v<MT2> ) >
346 {
348 
349  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
350  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
351 
352  addAssign( ~lhs, ~rhs );
353 }
355 //*************************************************************************************************
356 
357 
358 //*************************************************************************************************
376 template< typename MT1 // Type of the left-hand side dense matrix
377  , bool SO1 // Storage order of the left-hand side dense matrix
378  , typename MT2 // Type of the right-hand side matrix
379  , bool SO2 > // Storage order of the right-hand side matrix
380 inline auto smpAddAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
381  -> EnableIf_t< IsDenseMatrix_v<MT1> && IsSMPAssignable_v<MT1> && IsSMPAssignable_v<MT2> >
382 {
384 
385  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT1> );
386  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT2> );
387 
388  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
389  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
390 
391  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
392  addAssign( ~lhs, ~rhs );
393  }
394  else {
395  hpxAssign( ~lhs, ~rhs, AddAssign() );
396  }
397 }
399 //*************************************************************************************************
400 
401 
402 
403 
404 //=================================================================================================
405 //
406 // SUBTRACTION ASSIGNMENT
407 //
408 //=================================================================================================
409 
410 //*************************************************************************************************
428 template< typename MT1 // Type of the left-hand side dense matrix
429  , bool SO1 // Storage order of the left-hand side dense matrix
430  , typename MT2 // Type of the right-hand side matrix
431  , bool SO2 > // Storage order of the right-hand side matrix
432 inline auto smpSubAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
433  -> EnableIf_t< IsDenseMatrix_v<MT1> && ( !IsSMPAssignable_v<MT1> || !IsSMPAssignable_v<MT2> ) >
434 {
436 
437  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
438  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
439 
440  subAssign( ~lhs, ~rhs );
441 }
443 //*************************************************************************************************
444 
445 
446 //*************************************************************************************************
464 template< typename MT1 // Type of the left-hand side dense matrix
465  , bool SO1 // Storage order of the left-hand side dense matrix
466  , typename MT2 // Type of the right-hand side matrix
467  , bool SO2 > // Storage order of the right-hand side matrix
468 inline auto smpSubAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
469  -> EnableIf_t< IsDenseMatrix_v<MT1> && IsSMPAssignable_v<MT1> && IsSMPAssignable_v<MT2> >
470 {
472 
473  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT1> );
474  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT2> );
475 
476  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
477  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
478 
479  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
480  subAssign( ~lhs, ~rhs );
481  }
482  else {
483  hpxAssign( ~lhs, ~rhs, SubAssign() );
484  }
485 }
487 //*************************************************************************************************
488 
489 
490 
491 
492 //=================================================================================================
493 //
494 // SCHUR PRODUCT ASSIGNMENT
495 //
496 //=================================================================================================
497 
498 //*************************************************************************************************
516 template< typename MT1 // Type of the left-hand side dense matrix
517  , bool SO1 // Storage order of the left-hand side dense matrix
518  , typename MT2 // Type of the right-hand side matrix
519  , bool SO2 > // Storage order of the right-hand side matrix
520 inline auto smpSchurAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
521  -> EnableIf_t< IsDenseMatrix_v<MT1> && ( !IsSMPAssignable_v<MT1> || !IsSMPAssignable_v<MT2> ) >
522 {
524 
525  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
526  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
527 
528  schurAssign( ~lhs, ~rhs );
529 }
531 //*************************************************************************************************
532 
533 
534 //*************************************************************************************************
552 template< typename MT1 // Type of the left-hand side dense matrix
553  , bool SO1 // Storage order of the left-hand side dense matrix
554  , typename MT2 // Type of the right-hand side matrix
555  , bool SO2 > // Storage order of the right-hand side matrix
556 inline auto smpSchurAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
557  -> EnableIf_t< IsDenseMatrix_v<MT1> && IsSMPAssignable_v<MT1> && IsSMPAssignable_v<MT2> >
558 {
560 
561  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT1> );
562  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT2> );
563 
564  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
565  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
566 
567  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
568  schurAssign( ~lhs, ~rhs );
569  }
570  else {
571  hpxAssign( ~lhs, ~rhs, SchurAssign() );
572  }
573 }
575 //*************************************************************************************************
576 
577 
578 
579 
580 //=================================================================================================
581 //
582 // MULTIPLICATION ASSIGNMENT
583 //
584 //=================================================================================================
585 
586 //*************************************************************************************************
602 template< typename MT1 // Type of the left-hand side dense matrix
603  , bool SO1 // Storage order of the left-hand side matrix
604  , typename MT2 // Type of the right-hand side matrix
605  , bool SO2 > // Storage order of the right-hand side matrix
606 inline auto smpMultAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
607  -> EnableIf_t< IsDenseMatrix_v<MT1> >
608 {
610 
611  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
612  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
613 
614  multAssign( ~lhs, ~rhs );
615 }
617 //*************************************************************************************************
618 
619 
620 
621 
622 //=================================================================================================
623 //
624 // COMPILE TIME CONSTRAINT
625 //
626 //=================================================================================================
627 
628 //*************************************************************************************************
630 namespace {
631 
633 
634 }
636 //*************************************************************************************************
637 
638 } // namespace blaze
639 
640 #endif
Header file for the implementation of the Submatrix view.
Header file for auxiliary alias declarations.
decltype(auto) column(Matrix< MT, SO > &matrix, RCAs... args)
Creating a view on a specific column of the given matrix.
Definition: Column.h:133
Headerfile for the generic min algorithm.
Header file for the alignment flag values.
Header file for basic type definitions.
Header file for the Assign functor.
Header file for the AddAssign functor.
Header file for the SIMD trait.
constexpr size_t columns(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of columns of the matrix.
Definition: Matrix.h:514
Header file for the SparseMatrix base class.
Header file for the SMP thread mapping functionality.
Header file for the matrix storage order types.
#define BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE(T)
Constraint on the data type.In case the given data type T is SMP-assignable (can be assigned by multi...
Definition: SMPAssignable.h:81
#define BLAZE_HPX_PARALLEL_MODE
Compilation switch for the HPX parallelization.This compilation switch enables/disables the paralleli...
Definition: SMP.h:96
Namespace of the Blaze C++ math library.
Definition: Blaze.h:58
Header file for the SubAssign functor.
Compile time assertion.
System settings for the shared-memory parallelization.
Header file for the IsSMPAssignable type trait.
decltype(auto) min(const DenseMatrix< MT1, SO1 > &lhs, const DenseMatrix< MT2, SO2 > &rhs)
Computes the componentwise minimum of the dense matrices lhs and rhs.
Definition: DMatDMatMapExpr.h:1147
Header file for the DenseMatrix base class.
Header file for the serial section implementation.
Header file for the SchurAssign functor.
Header file for the IsDenseMatrix type trait.
Header file for the EnableIf class template.
bool isSerialSectionActive()
Returns whether a serial section is active or not.
Definition: SerialSection.h:213
Header file for the IsSIMDCombinable type trait.
Header file for run time assertion macros.
auto smpAddAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs) -> EnableIf_t< IsDenseMatrix_v< MT1 > >
Default implementation of the SMP addition assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:131
decltype(auto) row(Matrix< MT, SO > &, RRAs...)
Creating a view on a specific row of the given matrix.
Definition: Row.h:133
#define BLAZE_FUNCTION_TRACE
Function trace macro.This macro can be used to reliably trace function calls. In case function tracin...
Definition: FunctionTrace.h:94
constexpr size_t size(const Matrix< MT, SO > &matrix) noexcept
Returns the total number of elements of the matrix.
Definition: Matrix.h:530
auto smpAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs) -> EnableIf_t< IsDenseMatrix_v< MT1 > >
Default implementation of the SMP assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:100
auto smpSchurAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs) -> EnableIf_t< IsDenseMatrix_v< MT1 > >
Default implementation of the SMP Schur product assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:194
constexpr size_t rows(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of rows of the matrix.
Definition: Matrix.h:498
Header file for the MultAssign functor.
auto smpSubAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs) -> EnableIf_t< IsDenseMatrix_v< MT1 > >
Default implementation of the SMP subtraction assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:162
Header file for SMP utility functions.
#define BLAZE_STATIC_ASSERT(expr)
Compile time assertion macro.In case of an invalid compile time expression, a compilation error is cr...
Definition: StaticAssert.h:112
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_INTERNAL_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERTION flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:101
auto smpMultAssign(Vector< VT1, TF1 > &lhs, const Vector< VT2, TF2 > &rhs) -> EnableIf_t< IsDenseVector_v< VT1 > >
Default implementation of the SMP multiplication assignment of a vector to a dense vector...
Definition: DenseVector.h:191
BLAZE_ALWAYS_INLINE size_t getNumThreads()
Returns the number of threads used for thread parallel operations.
Definition: Functions.h:77
Constraint on the data type.
Header file for the function trace functionality.