Blaze  3.6
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>
57 #include <blaze/system/SMP.h>
59 #include <blaze/util/Assert.h>
60 #include <blaze/util/EnableIf.h>
63 #include <blaze/util/Types.h>
64 
65 
66 namespace blaze {
67 
68 //=================================================================================================
69 //
70 // THREAD-BASED ASSIGNMENT KERNELS
71 //
72 //=================================================================================================
73 
74 //*************************************************************************************************
91 template< typename MT1 // Type of the left-hand side dense matrix
92  , bool SO1 // Storage order of the left-hand side dense matrix
93  , typename MT2 // Type of the right-hand side dense matrix
94  , bool SO2 // Storage order of the right-hand side dense matrix
95  , typename OP > // Type of the assignment operation
96 void threadAssign( DenseMatrix<MT1,SO1>& lhs, const DenseMatrix<MT2,SO2>& rhs, OP op )
97 {
99 
100  BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
101 
102  using ET1 = ElementType_t<MT1>;
103  using ET2 = ElementType_t<MT2>;
104 
105  constexpr bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSIMDCombinable_v<ET1,ET2> );
106  constexpr size_t SIMDSIZE( SIMDTrait< ElementType_t<MT1> >::size );
107 
108  const bool lhsAligned( (~lhs).isAligned() );
109  const bool rhsAligned( (~rhs).isAligned() );
110 
111  const ThreadMapping threads( createThreadMapping( TheThreadBackend::size(), ~rhs ) );
112 
113  const size_t addon1 ( ( ( (~rhs).rows() % threads.first ) != 0UL )? 1UL : 0UL );
114  const size_t equalShare1( (~rhs).rows() / threads.first + addon1 );
115  const size_t rest1 ( equalShare1 & ( SIMDSIZE - 1UL ) );
116  const size_t rowsPerThread( ( simdEnabled && rest1 )?( equalShare1 - rest1 + SIMDSIZE ):( equalShare1 ) );
117 
118  const size_t addon2 ( ( ( (~rhs).columns() % threads.second ) != 0UL )? 1UL : 0UL );
119  const size_t equalShare2( (~rhs).columns() / threads.second + addon2 );
120  const size_t rest2 ( equalShare2 & ( SIMDSIZE - 1UL ) );
121  const size_t colsPerThread( ( simdEnabled && rest2 )?( equalShare2 - rest2 + SIMDSIZE ):( equalShare2 ) );
122 
123  for( size_t i=0UL; i<threads.first; ++i )
124  {
125  const size_t row( i*rowsPerThread );
126 
127  if( row >= (~lhs).rows() )
128  continue;
129 
130  for( size_t j=0UL; j<threads.second; ++j )
131  {
132  const size_t column( j*colsPerThread );
133 
134  if( column >= (~rhs).columns() )
135  continue;
136 
137  const size_t m( min( rowsPerThread, (~lhs).rows() - row ) );
138  const size_t n( min( colsPerThread, (~rhs).columns() - column ) );
139 
140  if( simdEnabled && lhsAligned && rhsAligned ) {
141  auto target( submatrix<aligned>( ~lhs, row, column, m, n, unchecked ) );
142  const auto source( submatrix<aligned>( ~rhs, row, column, m, n, unchecked ) );
143  TheThreadBackend::schedule( target, source, op );
144  }
145  else if( simdEnabled && lhsAligned ) {
146  auto target( submatrix<aligned>( ~lhs, row, column, m, n, unchecked ) );
147  const auto source( submatrix<unaligned>( ~rhs, row, column, m, n, unchecked ) );
148  TheThreadBackend::schedule( target, source, op );
149  }
150  else if( simdEnabled && rhsAligned ) {
151  auto target( submatrix<unaligned>( ~lhs, row, column, m, n, unchecked ) );
152  const auto source( submatrix<aligned>( ~rhs, row, column, m, n, unchecked ) );
153  TheThreadBackend::schedule( target, source, op );
154  }
155  else {
156  auto target( submatrix<unaligned>( ~lhs, row, column, m, n, unchecked ) );
157  const auto source( submatrix<unaligned>( ~rhs, row, column, m, n, unchecked ) );
158  TheThreadBackend::schedule( target, source, op );
159  }
160  }
161  }
162 
163  TheThreadBackend::wait();
164 }
166 //*************************************************************************************************
167 
168 
169 //*************************************************************************************************
187 template< typename MT1 // Type of the left-hand side dense matrix
188  , bool SO1 // Storage order of the left-hand side dense matrix
189  , typename MT2 // Type of the right-hand side sparse matrix
190  , bool SO2 // Storage order of the right-hand side sparse matrix
191  , typename OP > // Type of the assignment operation
192 void threadAssign( DenseMatrix<MT1,SO1>& lhs, const SparseMatrix<MT2,SO2>& rhs, OP op )
193 {
195 
196  BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
197 
198  const ThreadMapping threads( createThreadMapping( TheThreadBackend::size(), ~rhs ) );
199 
200  const size_t addon1 ( ( ( (~rhs).rows() % threads.first ) != 0UL )? 1UL : 0UL );
201  const size_t rowsPerThread( (~rhs).rows() / threads.first + addon1 );
202 
203  const size_t addon2 ( ( ( (~rhs).columns() % threads.second ) != 0UL )? 1UL : 0UL );
204  const size_t colsPerThread( (~rhs).columns() / threads.second + addon2 );
205 
206  for( size_t i=0UL; i<threads.first; ++i )
207  {
208  const size_t row( i*rowsPerThread );
209 
210  if( row >= (~lhs).rows() )
211  continue;
212 
213  for( size_t j=0UL; j<threads.second; ++j )
214  {
215  const size_t column( j*colsPerThread );
216 
217  if( column >= (~lhs).columns() )
218  continue;
219 
220  const size_t m( min( rowsPerThread, (~lhs).rows() - row ) );
221  const size_t n( min( colsPerThread, (~lhs).columns() - column ) );
222 
223  auto target( submatrix<unaligned>( ~lhs, row, column, m, n, unchecked ) );
224  const auto source( submatrix<unaligned>( ~rhs, row, column, m, n, unchecked ) );
225  TheThreadBackend::schedule( target, source, op );
226  }
227  }
228 
229  TheThreadBackend::wait();
230 }
232 //*************************************************************************************************
233 
234 
235 
236 
237 //=================================================================================================
238 //
239 // PLAIN ASSIGNMENT
240 //
241 //=================================================================================================
242 
243 //*************************************************************************************************
261 template< typename MT1 // Type of the left-hand side dense matrix
262  , bool SO1 // Storage order of the left-hand side dense matrix
263  , typename MT2 // Type of the right-hand side matrix
264  , bool SO2 > // Storage order of the right-hand side matrix
265 inline auto smpAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
266  -> EnableIf_t< IsDenseMatrix_v<MT1> && ( !IsSMPAssignable_v<MT1> || !IsSMPAssignable_v<MT2> ) >
267 {
269 
270  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
271  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
272 
273  assign( ~lhs, ~rhs );
274 }
276 //*************************************************************************************************
277 
278 
279 //*************************************************************************************************
297 template< typename MT1 // Type of the left-hand side dense matrix
298  , bool SO1 // Storage order of the left-hand side dense matrix
299  , typename MT2 // Type of the right-hand side matrix
300  , bool SO2 > // Storage order of the right-hand side matrix
301 inline auto smpAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
302  -> EnableIf_t< IsDenseMatrix_v<MT1> && IsSMPAssignable_v<MT1> && IsSMPAssignable_v<MT2> >
303 {
305 
306  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT1> );
307  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT2> );
308 
309  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
310  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
311 
313  {
314  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
315  assign( ~lhs, ~rhs );
316  }
317  else {
318  threadAssign( ~lhs, ~rhs, []( auto& a, const auto& b ){ assign( a, b ); } );
319  }
320  }
321 }
323 //*************************************************************************************************
324 
325 
326 
327 
328 //=================================================================================================
329 //
330 // ADDITION ASSIGNMENT
331 //
332 //=================================================================================================
333 
334 //*************************************************************************************************
353 template< typename MT1 // Type of the left-hand side dense matrix
354  , bool SO1 // Storage order of the left-hand side dense matrix
355  , typename MT2 // Type of the right-hand side matrix
356  , bool SO2 > // Storage order of the right-hand side matrix
357 inline auto smpAddAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
358  -> EnableIf_t< IsDenseMatrix_v<MT1> && ( !IsSMPAssignable_v<MT1> || !IsSMPAssignable_v<MT2> ) >
359 {
361 
362  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
363  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
364 
365  addAssign( ~lhs, ~rhs );
366 }
368 //*************************************************************************************************
369 
370 
371 //*************************************************************************************************
389 template< typename MT1 // Type of the left-hand side dense matrix
390  , bool SO1 // Storage order of the left-hand side dense matrix
391  , typename MT2 // Type of the right-hand side matrix
392  , bool SO2 > // Storage order of the right-hand side matrix
393 inline auto smpAddAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
394  -> EnableIf_t< IsDenseMatrix_v<MT1> && IsSMPAssignable_v<MT1> && IsSMPAssignable_v<MT2> >
395 {
397 
398  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT1> );
399  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT2> );
400 
401  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
402  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
403 
405  {
406  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
407  addAssign( ~lhs, ~rhs );
408  }
409  else {
410  threadAssign( ~lhs, ~rhs, []( auto& a, const auto& b ){ addAssign( a, b ); } );
411  }
412  }
413 }
415 //*************************************************************************************************
416 
417 
418 
419 
420 //=================================================================================================
421 //
422 // SUBTRACTION ASSIGNMENT
423 //
424 //=================================================================================================
425 
426 //*************************************************************************************************
445 template< typename MT1 // Type of the left-hand side dense matrix
446  , bool SO1 // Storage order of the left-hand side dense matrix
447  , typename MT2 // Type of the right-hand side matrix
448  , bool SO2 > // Storage order of the right-hand side matrix
449 inline auto smpSubAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
450  -> EnableIf_t< IsDenseMatrix_v<MT1> && ( !IsSMPAssignable_v<MT1> || !IsSMPAssignable_v<MT2> ) >
451 {
453 
454  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
455  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
456 
457  subAssign( ~lhs, ~rhs );
458 }
460 //*************************************************************************************************
461 
462 
463 //*************************************************************************************************
482 template< typename MT1 // Type of the left-hand side dense matrix
483  , bool SO1 // Storage order of the left-hand side dense matrix
484  , typename MT2 // Type of the right-hand side matrix
485  , bool SO2 > // Storage order of the right-hand side matrix
486 inline auto smpSubAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
487  -> EnableIf_t< IsDenseMatrix_v<MT1> && IsSMPAssignable_v<MT1> && IsSMPAssignable_v<MT2> >
488 {
490 
491  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT1> );
492  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT2> );
493 
494  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
495  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
496 
498  {
499  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
500  subAssign( ~lhs, ~rhs );
501  }
502  else {
503  threadAssign( ~lhs, ~rhs, []( auto& a, const auto& b ){ subAssign( a, b ); } );
504  }
505  }
506 }
508 //*************************************************************************************************
509 
510 
511 
512 
513 //=================================================================================================
514 //
515 // SCHUR PRODUCT ASSIGNMENT
516 //
517 //=================================================================================================
518 
519 //*************************************************************************************************
538 template< typename MT1 // Type of the left-hand side dense matrix
539  , bool SO1 // Storage order of the left-hand side dense matrix
540  , typename MT2 // Type of the right-hand side matrix
541  , bool SO2 > // Storage order of the right-hand side matrix
542 inline auto smpSchurAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
543  -> EnableIf_t< IsDenseMatrix_v<MT1> && ( !IsSMPAssignable_v<MT1> || !IsSMPAssignable_v<MT2> ) >
544 {
546 
547  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
548  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
549 
550  schurAssign( ~lhs, ~rhs );
551 }
553 //*************************************************************************************************
554 
555 
556 //*************************************************************************************************
575 template< typename MT1 // Type of the left-hand side dense matrix
576  , bool SO1 // Storage order of the left-hand side dense matrix
577  , typename MT2 // Type of the right-hand side matrix
578  , bool SO2 > // Storage order of the right-hand side matrix
579 inline auto smpSchurAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
580  -> EnableIf_t< IsDenseMatrix_v<MT1> && IsSMPAssignable_v<MT1> && IsSMPAssignable_v<MT2> >
581 {
583 
584  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT1> );
585  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT2> );
586 
587  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
588  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
589 
591  {
592  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
593  schurAssign( ~lhs, ~rhs );
594  }
595  else {
596  threadAssign( ~lhs, ~rhs, []( auto& a, const auto& b ){ schurAssign( a, b ); } );
597  }
598  }
599 }
601 //*************************************************************************************************
602 
603 
604 
605 
606 //=================================================================================================
607 //
608 // MULTIPLICATION ASSIGNMENT
609 //
610 //=================================================================================================
611 
612 //*************************************************************************************************
629 template< typename MT1 // Type of the left-hand side dense matrix
630  , bool SO1 // Storage order of the left-hand side matrix
631  , typename MT2 // Type of the right-hand side matrix
632  , bool SO2 > // Storage order of the right-hand side matrix
633 inline auto smpMultAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
634  -> EnableIf_t< IsDenseMatrix_v<MT1> >
635 {
637 
638  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
639  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
640 
641  multAssign( ~lhs, ~rhs );
642 }
644 //*************************************************************************************************
645 
646 
647 
648 
649 //=================================================================================================
650 //
651 // COMPILE TIME CONSTRAINT
652 //
653 //=================================================================================================
654 
655 //*************************************************************************************************
657 namespace {
658 
660 
661 }
663 //*************************************************************************************************
664 
665 } // namespace blaze
666 
667 #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.
#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 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
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:1162
Header file for the DenseMatrix base class.
Header file for the serial section implementation.
#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
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,...
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.