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>
68 #include <blaze/util/Types.h>
69 
70 
71 namespace blaze {
72 
73 //=================================================================================================
74 //
75 // THREAD-BASED ASSIGNMENT KERNELS
76 //
77 //=================================================================================================
78 
79 //*************************************************************************************************
96 template< typename MT1 // Type of the left-hand side dense matrix
97  , bool SO1 // Storage order of the left-hand side dense matrix
98  , typename MT2 // Type of the right-hand side dense matrix
99  , bool SO2 // Storage order of the right-hand side dense matrix
100  , typename OP > // Type of the assignment operation
101 void threadAssign( DenseMatrix<MT1,SO1>& lhs, const DenseMatrix<MT2,SO2>& rhs, OP op )
102 {
104 
105  BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
106 
107  using ET1 = ElementType_t<MT1>;
108  using ET2 = ElementType_t<MT2>;
109 
110  constexpr bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSIMDCombinable_v<ET1,ET2> );
111  constexpr size_t SIMDSIZE( SIMDTrait< ElementType_t<MT1> >::size );
112 
113  const bool lhsAligned( (~lhs).isAligned() );
114  const bool rhsAligned( (~rhs).isAligned() );
115 
116  const ThreadMapping threads( createThreadMapping( TheThreadBackend::size(), ~rhs ) );
117 
118  const size_t addon1 ( ( ( (~rhs).rows() % threads.first ) != 0UL )? 1UL : 0UL );
119  const size_t equalShare1( (~rhs).rows() / threads.first + addon1 );
120  const size_t rest1 ( equalShare1 & ( SIMDSIZE - 1UL ) );
121  const size_t rowsPerThread( ( simdEnabled && rest1 )?( equalShare1 - rest1 + SIMDSIZE ):( equalShare1 ) );
122 
123  const size_t addon2 ( ( ( (~rhs).columns() % threads.second ) != 0UL )? 1UL : 0UL );
124  const size_t equalShare2( (~rhs).columns() / threads.second + addon2 );
125  const size_t rest2 ( equalShare2 & ( SIMDSIZE - 1UL ) );
126  const size_t colsPerThread( ( simdEnabled && rest2 )?( equalShare2 - rest2 + SIMDSIZE ):( equalShare2 ) );
127 
128  for( size_t i=0UL; i<threads.first; ++i )
129  {
130  const size_t row( i*rowsPerThread );
131 
132  if( row >= (~lhs).rows() )
133  continue;
134 
135  for( size_t j=0UL; j<threads.second; ++j )
136  {
137  const size_t column( j*colsPerThread );
138 
139  if( column >= (~rhs).columns() )
140  continue;
141 
142  const size_t m( min( rowsPerThread, (~lhs).rows() - row ) );
143  const size_t n( min( colsPerThread, (~rhs).columns() - column ) );
144 
145  if( simdEnabled && lhsAligned && rhsAligned ) {
146  auto target( submatrix<aligned>( ~lhs, row, column, m, n, unchecked ) );
147  const auto source( submatrix<aligned>( ~rhs, row, column, m, n, unchecked ) );
148  TheThreadBackend::schedule( target, source, op );
149  }
150  else if( simdEnabled && lhsAligned ) {
151  auto target( submatrix<aligned>( ~lhs, row, column, m, n, unchecked ) );
152  const auto source( submatrix<unaligned>( ~rhs, row, column, m, n, unchecked ) );
153  TheThreadBackend::schedule( target, source, op );
154  }
155  else if( simdEnabled && rhsAligned ) {
156  auto target( submatrix<unaligned>( ~lhs, row, column, m, n, unchecked ) );
157  const auto source( submatrix<aligned>( ~rhs, row, column, m, n, unchecked ) );
158  TheThreadBackend::schedule( target, source, op );
159  }
160  else {
161  auto target( submatrix<unaligned>( ~lhs, row, column, m, n, unchecked ) );
162  const auto source( submatrix<unaligned>( ~rhs, row, column, m, n, unchecked ) );
163  TheThreadBackend::schedule( target, source, op );
164  }
165  }
166  }
167 
168  TheThreadBackend::wait();
169 }
171 //*************************************************************************************************
172 
173 
174 //*************************************************************************************************
192 template< typename MT1 // Type of the left-hand side dense matrix
193  , bool SO1 // Storage order of the left-hand side dense matrix
194  , typename MT2 // Type of the right-hand side sparse matrix
195  , bool SO2 // Storage order of the right-hand side sparse matrix
196  , typename OP > // Type of the assignment operation
197 void threadAssign( DenseMatrix<MT1,SO1>& lhs, const SparseMatrix<MT2,SO2>& rhs, OP op )
198 {
200 
201  BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
202 
203  const ThreadMapping threads( createThreadMapping( TheThreadBackend::size(), ~rhs ) );
204 
205  const size_t addon1 ( ( ( (~rhs).rows() % threads.first ) != 0UL )? 1UL : 0UL );
206  const size_t rowsPerThread( (~rhs).rows() / threads.first + addon1 );
207 
208  const size_t addon2 ( ( ( (~rhs).columns() % threads.second ) != 0UL )? 1UL : 0UL );
209  const size_t colsPerThread( (~rhs).columns() / threads.second + addon2 );
210 
211  for( size_t i=0UL; i<threads.first; ++i )
212  {
213  const size_t row( i*rowsPerThread );
214 
215  if( row >= (~lhs).rows() )
216  continue;
217 
218  for( size_t j=0UL; j<threads.second; ++j )
219  {
220  const size_t column( j*colsPerThread );
221 
222  if( column >= (~lhs).columns() )
223  continue;
224 
225  const size_t m( min( rowsPerThread, (~lhs).rows() - row ) );
226  const size_t n( min( colsPerThread, (~lhs).columns() - column ) );
227 
228  auto target( submatrix<unaligned>( ~lhs, row, column, m, n, unchecked ) );
229  const auto source( submatrix<unaligned>( ~rhs, row, column, m, n, unchecked ) );
230  TheThreadBackend::schedule( target, source, op );
231  }
232  }
233 
234  TheThreadBackend::wait();
235 }
237 //*************************************************************************************************
238 
239 
240 
241 
242 //=================================================================================================
243 //
244 // PLAIN ASSIGNMENT
245 //
246 //=================================================================================================
247 
248 //*************************************************************************************************
266 template< typename MT1 // Type of the left-hand side dense matrix
267  , bool SO1 // Storage order of the left-hand side dense matrix
268  , typename MT2 // Type of the right-hand side matrix
269  , bool SO2 > // Storage order of the right-hand side matrix
270 inline auto smpAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
271  -> EnableIf_t< IsDenseMatrix_v<MT1> && ( !IsSMPAssignable_v<MT1> || !IsSMPAssignable_v<MT2> ) >
272 {
274 
275  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
276  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
277 
278  assign( ~lhs, ~rhs );
279 }
281 //*************************************************************************************************
282 
283 
284 //*************************************************************************************************
302 template< typename MT1 // Type of the left-hand side dense matrix
303  , bool SO1 // Storage order of the left-hand side dense matrix
304  , typename MT2 // Type of the right-hand side matrix
305  , bool SO2 > // Storage order of the right-hand side matrix
306 inline auto smpAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
307  -> EnableIf_t< IsDenseMatrix_v<MT1> && IsSMPAssignable_v<MT1> && IsSMPAssignable_v<MT2> >
308 {
310 
311  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT1> );
312  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT2> );
313 
314  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
315  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
316 
318  {
319  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
320  assign( ~lhs, ~rhs );
321  }
322  else {
323  threadAssign( ~lhs, ~rhs, Assign() );
324  }
325  }
326 }
328 //*************************************************************************************************
329 
330 
331 
332 
333 //=================================================================================================
334 //
335 // ADDITION ASSIGNMENT
336 //
337 //=================================================================================================
338 
339 //*************************************************************************************************
358 template< typename MT1 // Type of the left-hand side dense matrix
359  , bool SO1 // Storage order of the left-hand side dense matrix
360  , typename MT2 // Type of the right-hand side matrix
361  , bool SO2 > // Storage order of the right-hand side matrix
362 inline auto smpAddAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
363  -> EnableIf_t< IsDenseMatrix_v<MT1> && ( !IsSMPAssignable_v<MT1> || !IsSMPAssignable_v<MT2> ) >
364 {
366 
367  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
368  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
369 
370  addAssign( ~lhs, ~rhs );
371 }
373 //*************************************************************************************************
374 
375 
376 //*************************************************************************************************
394 template< typename MT1 // Type of the left-hand side dense matrix
395  , bool SO1 // Storage order of the left-hand side dense matrix
396  , typename MT2 // Type of the right-hand side matrix
397  , bool SO2 > // Storage order of the right-hand side matrix
398 inline auto smpAddAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
399  -> EnableIf_t< IsDenseMatrix_v<MT1> && IsSMPAssignable_v<MT1> && IsSMPAssignable_v<MT2> >
400 {
402 
403  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT1> );
404  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT2> );
405 
406  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
407  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
408 
410  {
411  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
412  addAssign( ~lhs, ~rhs );
413  }
414  else {
415  threadAssign( ~lhs, ~rhs, AddAssign() );
416  }
417  }
418 }
420 //*************************************************************************************************
421 
422 
423 
424 
425 //=================================================================================================
426 //
427 // SUBTRACTION ASSIGNMENT
428 //
429 //=================================================================================================
430 
431 //*************************************************************************************************
450 template< typename MT1 // Type of the left-hand side dense matrix
451  , bool SO1 // Storage order of the left-hand side dense matrix
452  , typename MT2 // Type of the right-hand side matrix
453  , bool SO2 > // Storage order of the right-hand side matrix
454 inline auto smpSubAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
455  -> EnableIf_t< IsDenseMatrix_v<MT1> && ( !IsSMPAssignable_v<MT1> || !IsSMPAssignable_v<MT2> ) >
456 {
458 
459  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
460  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
461 
462  subAssign( ~lhs, ~rhs );
463 }
465 //*************************************************************************************************
466 
467 
468 //*************************************************************************************************
487 template< typename MT1 // Type of the left-hand side dense matrix
488  , bool SO1 // Storage order of the left-hand side dense matrix
489  , typename MT2 // Type of the right-hand side matrix
490  , bool SO2 > // Storage order of the right-hand side matrix
491 inline auto smpSubAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
492  -> EnableIf_t< IsDenseMatrix_v<MT1> && IsSMPAssignable_v<MT1> && IsSMPAssignable_v<MT2> >
493 {
495 
496  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT1> );
497  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT2> );
498 
499  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
500  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
501 
503  {
504  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
505  subAssign( ~lhs, ~rhs );
506  }
507  else {
508  threadAssign( ~lhs, ~rhs, SubAssign() );
509  }
510  }
511 }
513 //*************************************************************************************************
514 
515 
516 
517 
518 //=================================================================================================
519 //
520 // SCHUR PRODUCT ASSIGNMENT
521 //
522 //=================================================================================================
523 
524 //*************************************************************************************************
543 template< typename MT1 // Type of the left-hand side dense matrix
544  , bool SO1 // Storage order of the left-hand side dense matrix
545  , typename MT2 // Type of the right-hand side matrix
546  , bool SO2 > // Storage order of the right-hand side matrix
547 inline auto smpSchurAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
548  -> EnableIf_t< IsDenseMatrix_v<MT1> && ( !IsSMPAssignable_v<MT1> || !IsSMPAssignable_v<MT2> ) >
549 {
551 
552  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
553  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
554 
555  schurAssign( ~lhs, ~rhs );
556 }
558 //*************************************************************************************************
559 
560 
561 //*************************************************************************************************
580 template< typename MT1 // Type of the left-hand side dense matrix
581  , bool SO1 // Storage order of the left-hand side dense matrix
582  , typename MT2 // Type of the right-hand side matrix
583  , bool SO2 > // Storage order of the right-hand side matrix
584 inline auto smpSchurAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
585  -> EnableIf_t< IsDenseMatrix_v<MT1> && IsSMPAssignable_v<MT1> && IsSMPAssignable_v<MT2> >
586 {
588 
589  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT1> );
590  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT2> );
591 
592  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
593  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
594 
596  {
597  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
598  schurAssign( ~lhs, ~rhs );
599  }
600  else {
601  threadAssign( ~lhs, ~rhs, SchurAssign() );
602  }
603  }
604 }
606 //*************************************************************************************************
607 
608 
609 
610 
611 //=================================================================================================
612 //
613 // MULTIPLICATION ASSIGNMENT
614 //
615 //=================================================================================================
616 
617 //*************************************************************************************************
634 template< typename MT1 // Type of the left-hand side dense matrix
635  , bool SO1 // Storage order of the left-hand side matrix
636  , typename MT2 // Type of the right-hand side matrix
637  , bool SO2 > // Storage order of the right-hand side matrix
638 inline auto smpMultAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
639  -> EnableIf_t< IsDenseMatrix_v<MT1> >
640 {
642 
643  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
644  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
645 
646  multAssign( ~lhs, ~rhs );
647 }
649 //*************************************************************************************************
650 
651 
652 
653 
654 //=================================================================================================
655 //
656 // COMPILE TIME CONSTRAINT
657 //
658 //=================================================================================================
659 
660 //*************************************************************************************************
662 namespace {
663 
665 
666 }
668 //*************************************************************************************************
669 
670 } // namespace blaze
671 
672 #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 basic type definitions.
Header file for the Assign functor.
#define BLAZE_BOOST_THREADS_PARALLEL_MODE
Compilation switch for the Boost parallelization.This compilation switch enables/disables the paralle...
Definition: SMP.h:152
constexpr Unchecked unchecked
Global Unchecked instance.The blaze::unchecked instance is an optional token for the creation of view...
Definition: Check.h:138
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
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.
#define BLAZE_CPP_THREADS_PARALLEL_MODE
Compilation switch for the C++11 parallelization.This compilation switch enables/disables the paralle...
Definition: SMP.h:124
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:254
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
bool isParallelSectionActive()
Returns whether a parallel section is active or not.
Definition: ParallelSection.h:221
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 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
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
Constraint on the data type.
Header file for the function trace functionality.