DenseMatrix.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_SMP_THREADS_DENSEMATRIX_H_
36 #define _BLAZE_MATH_SMP_THREADS_DENSEMATRIX_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <blaze/math/Aliases.h>
62 #include <blaze/system/SMP.h>
64 #include <blaze/util/Assert.h>
65 #include <blaze/util/EnableIf.h>
67 #include <blaze/util/mpl/And.h>
68 #include <blaze/util/mpl/Not.h>
69 #include <blaze/util/mpl/Or.h>
71 #include <blaze/util/Types.h>
72 
73 
74 namespace blaze {
75 
76 //=================================================================================================
77 //
78 // THREAD-BASED ASSIGNMENT KERNELS
79 //
80 //=================================================================================================
81 
82 //*************************************************************************************************
99 template< typename MT1 // Type of the left-hand side dense matrix
100  , bool SO1 // Storage order of the left-hand side dense matrix
101  , typename MT2 // Type of the right-hand side dense matrix
102  , bool SO2 // Storage order of the right-hand side dense matrix
103  , typename OP > // Type of the assignment operation
104 void threadAssign( DenseMatrix<MT1,SO1>& lhs, const DenseMatrix<MT2,SO2>& rhs, OP op )
105 {
107 
108  BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
109 
110  using ET1 = ElementType_<MT1>;
111  using ET2 = ElementType_<MT2>;
112 
113  constexpr bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSIMDCombinable<ET1,ET2>::value );
114  constexpr size_t SIMDSIZE( SIMDTrait< ElementType_<MT1> >::size );
115 
116  const bool lhsAligned( (~lhs).isAligned() );
117  const bool rhsAligned( (~rhs).isAligned() );
118 
119  const ThreadMapping threads( createThreadMapping( TheThreadBackend::size(), ~rhs ) );
120 
121  const size_t addon1 ( ( ( (~rhs).rows() % threads.first ) != 0UL )? 1UL : 0UL );
122  const size_t equalShare1( (~rhs).rows() / threads.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() % threads.second ) != 0UL )? 1UL : 0UL );
127  const size_t equalShare2( (~rhs).columns() / threads.second + addon2 );
128  const size_t rest2 ( equalShare2 & ( SIMDSIZE - 1UL ) );
129  const size_t colsPerThread( ( simdEnabled && rest2 )?( equalShare2 - rest2 + SIMDSIZE ):( equalShare2 ) );
130 
131  for( size_t i=0UL; i<threads.first; ++i )
132  {
133  const size_t row( i*rowsPerThread );
134 
135  if( row >= (~lhs).rows() )
136  continue;
137 
138  for( size_t j=0UL; j<threads.second; ++j )
139  {
140  const size_t column( j*colsPerThread );
141 
142  if( column >= (~rhs).columns() )
143  continue;
144 
145  const size_t m( min( rowsPerThread, (~lhs).rows() - row ) );
146  const size_t n( min( colsPerThread, (~rhs).columns() - column ) );
147 
148  if( simdEnabled && lhsAligned && rhsAligned ) {
149  auto target( submatrix<aligned>( ~lhs, row, column, m, n, unchecked ) );
150  const auto source( submatrix<aligned>( ~rhs, row, column, m, n, unchecked ) );
151  TheThreadBackend::schedule( target, source, op );
152  }
153  else if( simdEnabled && lhsAligned ) {
154  auto target( submatrix<aligned>( ~lhs, row, column, m, n, unchecked ) );
155  const auto source( submatrix<unaligned>( ~rhs, row, column, m, n, unchecked ) );
156  TheThreadBackend::schedule( target, source, op );
157  }
158  else if( simdEnabled && rhsAligned ) {
159  auto target( submatrix<unaligned>( ~lhs, row, column, m, n, unchecked ) );
160  const auto source( submatrix<aligned>( ~rhs, row, column, m, n, unchecked ) );
161  TheThreadBackend::schedule( target, source, op );
162  }
163  else {
164  auto target( submatrix<unaligned>( ~lhs, row, column, m, n, unchecked ) );
165  const auto source( submatrix<unaligned>( ~rhs, row, column, m, n, unchecked ) );
166  TheThreadBackend::schedule( target, source, op );
167  }
168  }
169  }
170 
171  TheThreadBackend::wait();
172 }
174 //*************************************************************************************************
175 
176 
177 //*************************************************************************************************
195 template< typename MT1 // Type of the left-hand side dense matrix
196  , bool SO1 // Storage order of the left-hand side dense matrix
197  , typename MT2 // Type of the right-hand side sparse matrix
198  , bool SO2 // Storage order of the right-hand side sparse matrix
199  , typename OP > // Type of the assignment operation
200 void threadAssign( DenseMatrix<MT1,SO1>& lhs, const SparseMatrix<MT2,SO2>& rhs, OP op )
201 {
203 
204  BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
205 
206  const ThreadMapping threads( createThreadMapping( TheThreadBackend::size(), ~rhs ) );
207 
208  const size_t addon1 ( ( ( (~rhs).rows() % threads.first ) != 0UL )? 1UL : 0UL );
209  const size_t rowsPerThread( (~rhs).rows() / threads.first + addon1 );
210 
211  const size_t addon2 ( ( ( (~rhs).columns() % threads.second ) != 0UL )? 1UL : 0UL );
212  const size_t colsPerThread( (~rhs).columns() / threads.second + addon2 );
213 
214  for( size_t i=0UL; i<threads.first; ++i )
215  {
216  const size_t row( i*rowsPerThread );
217 
218  if( row >= (~lhs).rows() )
219  continue;
220 
221  for( size_t j=0UL; j<threads.second; ++j )
222  {
223  const size_t column( j*colsPerThread );
224 
225  if( column >= (~lhs).columns() )
226  continue;
227 
228  const size_t m( min( rowsPerThread, (~lhs).rows() - row ) );
229  const size_t n( min( colsPerThread, (~lhs).columns() - column ) );
230 
231  auto target( submatrix<unaligned>( ~lhs, row, column, m, n, unchecked ) );
232  const auto source( submatrix<unaligned>( ~rhs, row, column, m, n, unchecked ) );
233  TheThreadBackend::schedule( target, source, op );
234  }
235  }
236 
237  TheThreadBackend::wait();
238 }
240 //*************************************************************************************************
241 
242 
243 
244 
245 //=================================================================================================
246 //
247 // PLAIN ASSIGNMENT
248 //
249 //=================================================================================================
250 
251 //*************************************************************************************************
269 template< typename MT1 // Type of the left-hand side dense matrix
270  , bool SO1 // Storage order of the left-hand side dense matrix
271  , typename MT2 // Type of the right-hand side matrix
272  , bool SO2 > // Storage order of the right-hand side matrix
273 inline EnableIf_< And< IsDenseMatrix<MT1>
274  , Or< Not< IsSMPAssignable<MT1> >
275  , Not< IsSMPAssignable<MT2> > > > >
276  smpAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
277 {
279 
280  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
281  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
282 
283  assign( ~lhs, ~rhs );
284 }
286 //*************************************************************************************************
287 
288 
289 //*************************************************************************************************
307 template< typename MT1 // Type of the left-hand side dense matrix
308  , bool SO1 // Storage order of the left-hand side dense matrix
309  , typename MT2 // Type of the right-hand side matrix
310  , bool SO2 > // Storage order of the right-hand side matrix
311 inline EnableIf_< And< IsDenseMatrix<MT1>, IsSMPAssignable<MT1>, IsSMPAssignable<MT2> > >
312  smpAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
313 {
315 
316  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT1> );
317  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT2> );
318 
319  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
320  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
321 
323  {
324  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
325  assign( ~lhs, ~rhs );
326  }
327  else {
328  threadAssign( ~lhs, ~rhs, Assign() );
329  }
330  }
331 }
333 //*************************************************************************************************
334 
335 
336 
337 
338 //=================================================================================================
339 //
340 // ADDITION ASSIGNMENT
341 //
342 //=================================================================================================
343 
344 //*************************************************************************************************
363 template< typename MT1 // Type of the left-hand side dense matrix
364  , bool SO1 // Storage order of the left-hand side dense matrix
365  , typename MT2 // Type of the right-hand side matrix
366  , bool SO2 > // Storage order of the right-hand side matrix
367 inline EnableIf_< And< IsDenseMatrix<MT1>
368  , Or< Not< IsSMPAssignable<MT1> >
369  , Not< IsSMPAssignable<MT2> > > > >
370  smpAddAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
371 {
373 
374  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
375  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
376 
377  addAssign( ~lhs, ~rhs );
378 }
380 //*************************************************************************************************
381 
382 
383 //*************************************************************************************************
401 template< typename MT1 // Type of the left-hand side dense matrix
402  , bool SO1 // Storage order of the left-hand side dense matrix
403  , typename MT2 // Type of the right-hand side matrix
404  , bool SO2 > // Storage order of the right-hand side matrix
405 inline EnableIf_< And< IsDenseMatrix<MT1>, IsSMPAssignable<MT1>, IsSMPAssignable<MT2> > >
406  smpAddAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
407 {
409 
410  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT1> );
411  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT2> );
412 
413  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
414  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
415 
417  {
418  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
419  addAssign( ~lhs, ~rhs );
420  }
421  else {
422  threadAssign( ~lhs, ~rhs, AddAssign() );
423  }
424  }
425 }
427 //*************************************************************************************************
428 
429 
430 
431 
432 //=================================================================================================
433 //
434 // SUBTRACTION ASSIGNMENT
435 //
436 //=================================================================================================
437 
438 //*************************************************************************************************
457 template< typename MT1 // Type of the left-hand side dense matrix
458  , bool SO1 // Storage order of the left-hand side dense matrix
459  , typename MT2 // Type of the right-hand side matrix
460  , bool SO2 > // Storage order of the right-hand side matrix
461 inline EnableIf_< And< IsDenseMatrix<MT1>
462  , Or< Not< IsSMPAssignable<MT1> >
463  , Not< IsSMPAssignable<MT2> > > > >
464  smpSubAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
465 {
467 
468  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
469  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
470 
471  subAssign( ~lhs, ~rhs );
472 }
474 //*************************************************************************************************
475 
476 
477 //*************************************************************************************************
496 template< typename MT1 // Type of the left-hand side dense matrix
497  , bool SO1 // Storage order of the left-hand side dense matrix
498  , typename MT2 // Type of the right-hand side matrix
499  , bool SO2 > // Storage order of the right-hand side matrix
500 inline EnableIf_< And< IsDenseMatrix<MT1>, IsSMPAssignable<MT1>, IsSMPAssignable<MT2> > >
501  smpSubAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
502 {
504 
505  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT1> );
506  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT2> );
507 
508  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
509  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
510 
512  {
513  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
514  subAssign( ~lhs, ~rhs );
515  }
516  else {
517  threadAssign( ~lhs, ~rhs, SubAssign() );
518  }
519  }
520 }
522 //*************************************************************************************************
523 
524 
525 
526 
527 //=================================================================================================
528 //
529 // SCHUR PRODUCT ASSIGNMENT
530 //
531 //=================================================================================================
532 
533 //*************************************************************************************************
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 EnableIf_< And< IsDenseMatrix<MT1>
557  , Or< Not< IsSMPAssignable<MT1> >
558  , Not< IsSMPAssignable<MT2> > > > >
559  smpSchurAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
560 {
562 
563  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
564  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
565 
566  schurAssign( ~lhs, ~rhs );
567 }
569 //*************************************************************************************************
570 
571 
572 //*************************************************************************************************
591 template< typename MT1 // Type of the left-hand side dense matrix
592  , bool SO1 // Storage order of the left-hand side dense matrix
593  , typename MT2 // Type of the right-hand side matrix
594  , bool SO2 > // Storage order of the right-hand side matrix
595 inline EnableIf_< And< IsDenseMatrix<MT1>, IsSMPAssignable<MT1>, IsSMPAssignable<MT2> > >
596  smpSchurAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
597 {
599 
600  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT1> );
601  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<MT2> );
602 
603  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
604  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
605 
607  {
608  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
609  schurAssign( ~lhs, ~rhs );
610  }
611  else {
612  threadAssign( ~lhs, ~rhs, SchurAssign() );
613  }
614  }
615 }
617 //*************************************************************************************************
618 
619 
620 
621 
622 //=================================================================================================
623 //
624 // MULTIPLICATION ASSIGNMENT
625 //
626 //=================================================================================================
627 
628 //*************************************************************************************************
645 template< typename MT1 // Type of the left-hand side dense matrix
646  , bool SO1 // Storage order of the left-hand side matrix
647  , typename MT2 // Type of the right-hand side matrix
648  , bool SO2 > // Storage order of the right-hand side matrix
649 inline EnableIf_< IsDenseMatrix<MT1> >
650  smpMultAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
651 {
653 
654  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
655  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
656 
657  multAssign( ~lhs, ~rhs );
658 }
660 //*************************************************************************************************
661 
662 
663 
664 
665 //=================================================================================================
666 //
667 // COMPILE TIME CONSTRAINT
668 //
669 //=================================================================================================
670 
671 //*************************************************************************************************
673 namespace {
674 
676 
677 }
679 //*************************************************************************************************
680 
681 } // namespace blaze
682 
683 #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.
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
Header file for the Assign functor.
BLAZE_ALWAYS_INLINE size_t size(const Vector< VT, TF > &vector) noexcept
Returns the current size/dimension of the vector.
Definition: Vector.h:265
#define BLAZE_BOOST_THREADS_PARALLEL_MODE
Compilation switch for the Boost parallelization.This compilation switch enables/disables the paralle...
Definition: SMP.h:122
constexpr Unchecked unchecked
Global Unchecked instance.The blaze::unchecked instance is an optional token for the creation of view...
Definition: Check.h:138
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 AddAssign functor.
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
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.
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 SchurAssign functor.
#define BLAZE_CPP_THREADS_PARALLEL_MODE
Compilation switch for the C++11 parallelization.This compilation switch enables/disables the paralle...
Definition: SMP.h:95
Header file for the parallel section implementation.
Header file for the IsDenseMatrix type trait.
Header file for the EnableIf class template.
#define BLAZE_PARALLEL_SECTION
Section for the debugging of the shared-memory parallelization.During the shared-memory parallel (SMP...
Definition: ParallelSection.h:246
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 the MultAssign functor.
Header file for the C++11 and Boost thread backend.
#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
Constraint on the data type.
Header file for the function trace functionality.