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>
58 #include <blaze/system/SMP.h>
60 #include <blaze/util/Assert.h>
61 #include <blaze/util/EnableIf.h>
63 #include <blaze/util/mpl/And.h>
64 #include <blaze/util/mpl/Not.h>
65 #include <blaze/util/mpl/Or.h>
67 #include <blaze/util/Types.h>
68 
69 
70 namespace blaze {
71 
72 //=================================================================================================
73 //
74 // HPX-BASED ASSIGNMENT KERNELS
75 //
76 //=================================================================================================
77 
78 //*************************************************************************************************
95 template< typename MT1 // Type of the left-hand side dense matrix
96  , bool SO1 // Storage order of the left-hand side dense matrix
97  , typename MT2 // Type of the right-hand side dense matrix
98  , bool SO2 // Storage order of the right-hand side dense matrix
99  , typename OP > // Type of the assignment operation
100 void hpxAssign( DenseMatrix<MT1,SO1>& lhs, const DenseMatrix<MT2,SO2>& rhs, OP op )
101 {
102  using hpx::parallel::for_loop;
103  using hpx::parallel::execution::par;
104 
106 
107  BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
108 
109  using ET1 = ElementType_<MT1>;
110  using ET2 = ElementType_<MT2>;
111 
112  constexpr bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSIMDCombinable<ET1,ET2>::value );
113  constexpr size_t SIMDSIZE( SIMDTrait< ElementType_<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  BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
198 
199  const size_t threads ( getNumThreads() );
200  const ThreadMapping threadmap( createThreadMapping( threads, ~rhs ) );
201 
202  const size_t addon1 ( ( ( (~rhs).rows() % threadmap.first ) != 0UL )? 1UL : 0UL );
203  const size_t rowsPerThread( (~rhs).rows() / threadmap.first + addon1 );
204 
205  const size_t addon2 ( ( ( (~rhs).columns() % threadmap.second ) != 0UL )? 1UL : 0UL );
206  const size_t colsPerThread( (~rhs).columns() / threadmap.second + addon2 );
207 
208  for_loop( par, size_t(0), threads, [&](int i)
209  {
210  const size_t row ( ( i / threadmap.second ) * rowsPerThread );
211  const size_t column( ( i % threadmap.second ) * colsPerThread );
212 
213  if( row >= (~rhs).rows() || column >= (~rhs).columns() )
214  return;
215 
216  const size_t m( min( rowsPerThread, (~lhs).rows() - row ) );
217  const size_t n( min( colsPerThread, (~lhs).columns() - column ) );
218 
219  auto target( submatrix<unaligned>( ~lhs, row, column, m, n ) );
220  const auto source( submatrix<unaligned>( ~rhs, row, column, m, n ) );
221  op( target, source );
222  } );
223 }
225 //*************************************************************************************************
226 
227 
228 
229 
230 //=================================================================================================
231 //
232 // PLAIN ASSIGNMENT
233 //
234 //=================================================================================================
235 
236 //*************************************************************************************************
254 template< typename MT1 // Type of the left-hand side dense matrix
255  , bool SO1 // Storage order of the left-hand side dense matrix
256  , typename MT2 // Type of the right-hand side matrix
257  , bool SO2 > // Storage order of the right-hand side matrix
258 inline EnableIf_< And< IsDenseMatrix<MT1>
259  , Or< Not< IsSMPAssignable<MT1> >
260  , Not< IsSMPAssignable<MT2> > > > >
261  smpAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
262 {
264 
265  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
266  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
267 
268  assign( ~lhs, ~rhs );
269 }
271 //*************************************************************************************************
272 
273 
274 //*************************************************************************************************
292 template< typename MT1 // Type of the left-hand side dense matrix
293  , bool SO1 // Storage order of the left-hand side dense matrix
294  , typename MT2 // Type of the right-hand side matrix
295  , bool SO2 > // Storage order of the right-hand side matrix
296 inline EnableIf_< And< IsDenseMatrix<MT1>, IsSMPAssignable<MT1>, IsSMPAssignable<MT2> > >
297  smpAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
298 {
300 
301  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT1> );
302  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT2> );
303 
304  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
305  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
306 
307  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
308  assign( ~lhs, ~rhs );
309  }
310  else {
311  hpxAssign( ~lhs, ~rhs, Assign() );
312  }
313 }
315 //*************************************************************************************************
316 
317 
318 
319 
320 //=================================================================================================
321 //
322 // ADDITION ASSIGNMENT
323 //
324 //=================================================================================================
325 
326 //*************************************************************************************************
344 template< typename MT1 // Type of the left-hand side dense matrix
345  , bool SO1 // Storage order of the left-hand side dense matrix
346  , typename MT2 // Type of the right-hand side matrix
347  , bool SO2 > // Storage order of the right-hand side matrix
348 inline EnableIf_< And< IsDenseMatrix<MT1>
349  , Or< Not< IsSMPAssignable<MT1> >
350  , Not< IsSMPAssignable<MT2> > > > >
351  smpAddAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
352 {
354 
355  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
356  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
357 
358  addAssign( ~lhs, ~rhs );
359 }
361 //*************************************************************************************************
362 
363 
364 //*************************************************************************************************
382 template< typename MT1 // Type of the left-hand side dense matrix
383  , bool SO1 // Storage order of the left-hand side dense matrix
384  , typename MT2 // Type of the right-hand side matrix
385  , bool SO2 > // Storage order of the right-hand side matrix
386 inline EnableIf_< And< IsDenseMatrix<MT1>, IsSMPAssignable<MT1>, IsSMPAssignable<MT2> > >
387  smpAddAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
388 {
390 
391  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT1> );
392  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT2> );
393 
394  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
395  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
396 
397  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
398  addAssign( ~lhs, ~rhs );
399  }
400  else {
401  hpxAssign( ~lhs, ~rhs, AddAssign() );
402  }
403 }
405 //*************************************************************************************************
406 
407 
408 
409 
410 //=================================================================================================
411 //
412 // SUBTRACTION ASSIGNMENT
413 //
414 //=================================================================================================
415 
416 //*************************************************************************************************
434 template< typename MT1 // Type of the left-hand side dense matrix
435  , bool SO1 // Storage order of the left-hand side dense matrix
436  , typename MT2 // Type of the right-hand side matrix
437  , bool SO2 > // Storage order of the right-hand side matrix
438 inline EnableIf_< And< IsDenseMatrix<MT1>
439  , Or< Not< IsSMPAssignable<MT1> >
440  , Not< IsSMPAssignable<MT2> > > > >
441  smpSubAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
442 {
444 
445  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
446  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
447 
448  subAssign( ~lhs, ~rhs );
449 }
451 //*************************************************************************************************
452 
453 
454 //*************************************************************************************************
472 template< typename MT1 // Type of the left-hand side dense matrix
473  , bool SO1 // Storage order of the left-hand side dense matrix
474  , typename MT2 // Type of the right-hand side matrix
475  , bool SO2 > // Storage order of the right-hand side matrix
476 inline EnableIf_< And< IsDenseMatrix<MT1>, IsSMPAssignable<MT1>, IsSMPAssignable<MT2> > >
477  smpSubAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
478 {
480 
481  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT1> );
482  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT2> );
483 
484  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
485  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
486 
487  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
488  subAssign( ~lhs, ~rhs );
489  }
490  else {
491  hpxAssign( ~lhs, ~rhs, SubAssign() );
492  }
493 }
495 //*************************************************************************************************
496 
497 
498 
499 
500 //=================================================================================================
501 //
502 // SCHUR PRODUCT ASSIGNMENT
503 //
504 //=================================================================================================
505 
506 //*************************************************************************************************
524 template< typename MT1 // Type of the left-hand side dense matrix
525  , bool SO1 // Storage order of the left-hand side dense matrix
526  , typename MT2 // Type of the right-hand side matrix
527  , bool SO2 > // Storage order of the right-hand side matrix
528 inline EnableIf_< And< IsDenseMatrix<MT1>
529  , Or< Not< IsSMPAssignable<MT1> >
530  , Not< IsSMPAssignable<MT2> > > > >
531  smpSchurAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
532 {
534 
535  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
536  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
537 
538  schurAssign( ~lhs, ~rhs );
539 }
541 //*************************************************************************************************
542 
543 
544 //*************************************************************************************************
562 template< typename MT1 // Type of the left-hand side dense matrix
563  , bool SO1 // Storage order of the left-hand side dense matrix
564  , typename MT2 // Type of the right-hand side matrix
565  , bool SO2 > // Storage order of the right-hand side matrix
566 inline EnableIf_< And< IsDenseMatrix<MT1>, IsSMPAssignable<MT1>, IsSMPAssignable<MT2> > >
567  smpSchurAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
568 {
570 
571  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT1> );
572  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT2> );
573 
574  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
575  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
576 
577  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
578  schurAssign( ~lhs, ~rhs );
579  }
580  else {
581  hpxAssign( ~lhs, ~rhs, SchurAssign() );
582  }
583 }
585 //*************************************************************************************************
586 
587 
588 
589 
590 //=================================================================================================
591 //
592 // MULTIPLICATION ASSIGNMENT
593 //
594 //=================================================================================================
595 
596 //*************************************************************************************************
612 template< typename MT1 // Type of the left-hand side dense matrix
613  , bool SO1 // Storage order of the left-hand side matrix
614  , typename MT2 // Type of the right-hand side matrix
615  , bool SO2 > // Storage order of the right-hand side matrix
616 inline EnableIf_< IsDenseMatrix<MT1> >
617  smpMultAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
618 {
620 
621  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
622  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
623 
624  multAssign( ~lhs, ~rhs );
625 }
627 //*************************************************************************************************
628 
629 
630 
631 
632 //=================================================================================================
633 //
634 // COMPILE TIME CONSTRAINT
635 //
636 //=================================================================================================
637 
638 //*************************************************************************************************
640 namespace {
641 
643 
644 }
646 //*************************************************************************************************
647 
648 } // namespace blaze
649 
650 #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:131
Headerfile for the generic min algorithm.
Header file for the alignment flag values.
EnableIf_< IsDenseMatrix< MT1 > > smpSchurAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP Schur product assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:196
Header file for basic type definitions.
EnableIf_< IsDenseMatrix< MT1 > > smpSubAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP subtraction assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:164
BLAZE_ALWAYS_INLINE size_t size(const Vector< VT, TF > &vector) noexcept
Returns the current size/dimension of the vector.
Definition: Vector.h:265
EnableIf_< IsDenseVector< VT1 > > smpMultAssign(Vector< VT1, TF1 > &lhs, const Vector< VT2, TF2 > &rhs)
Default implementation of the SMP multiplication assignment of a vector to a dense vector...
Definition: DenseVector.h:193
Header file for the And class template.
const ElementType_< MT > min(const DenseMatrix< MT, SO > &dm)
Returns the smallest element of the dense matrix.
Definition: DenseMatrix.h:1903
Header file for the SIMD trait.
EnableIf_< IsDenseMatrix< MT1 > > smpAddAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP addition assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:133
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:148
Namespace of the Blaze C++ math library.
Definition: Blaze.h:58
Compile time assertion.
System settings for the shared-memory parallelization.
Header file for the IsSMPAssignable type trait.
EnableIf_< IsDenseMatrix< MT1 > > smpAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:102
Header file for the Or class template.
Header file for the DenseMatrix base class.
Header file for the Not class template.
BLAZE_ALWAYS_INLINE size_t columns(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of columns of the matrix.
Definition: Matrix.h:506
Header file for the serial section implementation.
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.
decltype(auto) row(Matrix< MT, SO > &, RRAs...)
Creating a view on a specific row of the given matrix.
Definition: Row.h:131
#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
BLAZE_ALWAYS_INLINE size_t rows(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of rows of the matrix.
Definition: Matrix.h:490
bool isParallelSectionActive()
Returns whether a parallel section is active or not.
Definition: ParallelSection.h:213
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
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.