Blaze  3.6
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>
64 #include <blaze/util/Types.h>
65 
66 
67 namespace blaze {
68 
69 //=================================================================================================
70 //
71 // HPX-BASED ASSIGNMENT KERNELS
72 //
73 //=================================================================================================
74 
75 //*************************************************************************************************
92 template< typename MT1 // Type of the left-hand side dense matrix
93  , bool SO1 // Storage order of the left-hand side dense matrix
94  , typename MT2 // Type of the right-hand side dense matrix
95  , bool SO2 // Storage order of the right-hand side dense matrix
96  , typename OP > // Type of the assignment operation
97 void hpxAssign( DenseMatrix<MT1,SO1>& lhs, const DenseMatrix<MT2,SO2>& rhs, OP op )
98 {
99  using hpx::parallel::for_loop;
100  using hpx::parallel::execution::par;
101 
103 
104  using ET1 = ElementType_t<MT1>;
105  using ET2 = ElementType_t<MT2>;
106 
107  constexpr bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSIMDCombinable_v<ET1,ET2> );
108  constexpr size_t SIMDSIZE( SIMDTrait< ElementType_t<MT1> >::size );
109 
110  const bool lhsAligned( (~lhs).isAligned() );
111  const bool rhsAligned( (~rhs).isAligned() );
112 
113  const size_t threads ( getNumThreads() );
114  const ThreadMapping threadmap( createThreadMapping( threads, ~rhs ) );
115 
116  const size_t addon1 ( ( ( (~rhs).rows() % threadmap.first ) != 0UL )? 1UL : 0UL );
117  const size_t equalShare1( (~rhs).rows() / threadmap.first + addon1 );
118  const size_t rest1 ( equalShare1 & ( SIMDSIZE - 1UL ) );
119  const size_t rowsPerThread( ( simdEnabled && rest1 )?( equalShare1 - rest1 + SIMDSIZE ):( equalShare1 ) );
120 
121  const size_t addon2 ( ( ( (~rhs).columns() % threadmap.second ) != 0UL )? 1UL : 0UL );
122  const size_t equalShare2( (~rhs).columns() / threadmap.second + addon2 );
123  const size_t rest2 ( equalShare2 & ( SIMDSIZE - 1UL ) );
124  const size_t colsPerThread( ( simdEnabled && rest2 )?( equalShare2 - rest2 + SIMDSIZE ):( equalShare2 ) );
125 
126  for_loop( par, size_t(0), threads, [&](int i)
127  {
128  const size_t row ( ( i / threadmap.second ) * rowsPerThread );
129  const size_t column( ( i % threadmap.second ) * colsPerThread );
130 
131  if( row >= (~rhs).rows() || column >= (~rhs).columns() )
132  return;
133 
134  const size_t m( min( rowsPerThread, (~rhs).rows() - row ) );
135  const size_t n( min( colsPerThread, (~rhs).columns() - column ) );
136 
137  if( simdEnabled && lhsAligned && rhsAligned ) {
138  auto target( submatrix<aligned>( ~lhs, row, column, m, n ) );
139  const auto source( submatrix<aligned>( ~rhs, row, column, m, n ) );
140  op( target, source );
141  }
142  else if( simdEnabled && lhsAligned ) {
143  auto target( submatrix<aligned>( ~lhs, row, column, m, n ) );
144  const auto source( submatrix<unaligned>( ~rhs, row, column, m, n ) );
145  op( target, source );
146  }
147  else if( simdEnabled && rhsAligned ) {
148  auto target( submatrix<unaligned>( ~lhs, row, column, m, n ) );
149  const auto source( submatrix<aligned>( ~rhs, row, column, m, n ) );
150  op( target, source );
151  }
152  else {
153  auto target( submatrix<unaligned>( ~lhs, row, column, m, n ) );
154  const auto source( submatrix<unaligned>( ~rhs, row, column, m, n ) );
155  op( target, source );
156  }
157  } );
158 }
160 //*************************************************************************************************
161 
162 
163 //*************************************************************************************************
180 template< typename MT1 // Type of the left-hand side dense matrix
181  , bool SO1 // Storage order of the left-hand side dense matrix
182  , typename MT2 // Type of the right-hand side sparse matrix
183  , bool SO2 // Storage order of the right-hand side sparse matrix
184  , typename OP > // Type of the assignment operation
185 void hpxAssign( DenseMatrix<MT1,SO1>& lhs, const SparseMatrix<MT2,SO2>& rhs, OP op )
186 {
187  using hpx::parallel::for_loop;
188  using hpx::parallel::execution::par;
189 
191 
192  const size_t threads ( getNumThreads() );
193  const ThreadMapping threadmap( createThreadMapping( threads, ~rhs ) );
194 
195  const size_t addon1 ( ( ( (~rhs).rows() % threadmap.first ) != 0UL )? 1UL : 0UL );
196  const size_t rowsPerThread( (~rhs).rows() / threadmap.first + addon1 );
197 
198  const size_t addon2 ( ( ( (~rhs).columns() % threadmap.second ) != 0UL )? 1UL : 0UL );
199  const size_t colsPerThread( (~rhs).columns() / threadmap.second + addon2 );
200 
201  for_loop( par, size_t(0), threads, [&](int i)
202  {
203  const size_t row ( ( i / threadmap.second ) * rowsPerThread );
204  const size_t column( ( i % threadmap.second ) * colsPerThread );
205 
206  if( row >= (~rhs).rows() || column >= (~rhs).columns() )
207  return;
208 
209  const size_t m( min( rowsPerThread, (~lhs).rows() - row ) );
210  const size_t n( min( colsPerThread, (~lhs).columns() - column ) );
211 
212  auto target( submatrix<unaligned>( ~lhs, row, column, m, n ) );
213  const auto source( submatrix<unaligned>( ~rhs, row, column, m, n ) );
214  op( target, source );
215  } );
216 }
218 //*************************************************************************************************
219 
220 
221 
222 
223 //=================================================================================================
224 //
225 // PLAIN ASSIGNMENT
226 //
227 //=================================================================================================
228 
229 //*************************************************************************************************
247 template< typename MT1 // Type of the left-hand side dense matrix
248  , bool SO1 // Storage order of the left-hand side dense matrix
249  , typename MT2 // Type of the right-hand side matrix
250  , bool SO2 > // Storage order of the right-hand side matrix
251 inline auto smpAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
252  -> EnableIf_t< IsDenseMatrix_v<MT1> && ( !IsSMPAssignable_v<MT1> || !IsSMPAssignable_v<MT2> ) >
253 {
255 
256  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
257  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
258 
259  assign( ~lhs, ~rhs );
260 }
262 //*************************************************************************************************
263 
264 
265 //*************************************************************************************************
283 template< typename MT1 // Type of the left-hand side dense matrix
284  , bool SO1 // Storage order of the left-hand side dense matrix
285  , typename MT2 // Type of the right-hand side matrix
286  , bool SO2 > // Storage order of the right-hand side matrix
287 inline auto smpAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
288  -> EnableIf_t< IsDenseMatrix_v<MT1> && IsSMPAssignable_v<MT1> && IsSMPAssignable_v<MT2> >
289 {
291 
292  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT1> );
293  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT2> );
294 
295  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
296  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
297 
298  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
299  assign( ~lhs, ~rhs );
300  }
301  else {
302  hpxAssign( ~lhs, ~rhs, []( auto& a, const auto& b ){ assign( a, b ); } );
303  }
304 }
306 //*************************************************************************************************
307 
308 
309 
310 
311 //=================================================================================================
312 //
313 // ADDITION ASSIGNMENT
314 //
315 //=================================================================================================
316 
317 //*************************************************************************************************
335 template< typename MT1 // Type of the left-hand side dense matrix
336  , bool SO1 // Storage order of the left-hand side dense matrix
337  , typename MT2 // Type of the right-hand side matrix
338  , bool SO2 > // Storage order of the right-hand side matrix
339 inline auto smpAddAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
340  -> EnableIf_t< IsDenseMatrix_v<MT1> && ( !IsSMPAssignable_v<MT1> || !IsSMPAssignable_v<MT2> ) >
341 {
343 
344  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
345  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
346 
347  addAssign( ~lhs, ~rhs );
348 }
350 //*************************************************************************************************
351 
352 
353 //*************************************************************************************************
371 template< typename MT1 // Type of the left-hand side dense matrix
372  , bool SO1 // Storage order of the left-hand side dense matrix
373  , typename MT2 // Type of the right-hand side matrix
374  , bool SO2 > // Storage order of the right-hand side matrix
375 inline auto smpAddAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
376  -> EnableIf_t< IsDenseMatrix_v<MT1> && IsSMPAssignable_v<MT1> && IsSMPAssignable_v<MT2> >
377 {
379 
380  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT1> );
381  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT2> );
382 
383  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
384  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
385 
386  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
387  addAssign( ~lhs, ~rhs );
388  }
389  else {
390  hpxAssign( ~lhs, ~rhs, []( auto& a, const auto& b ){ addAssign( a, b ); } );
391  }
392 }
394 //*************************************************************************************************
395 
396 
397 
398 
399 //=================================================================================================
400 //
401 // SUBTRACTION ASSIGNMENT
402 //
403 //=================================================================================================
404 
405 //*************************************************************************************************
423 template< typename MT1 // Type of the left-hand side dense matrix
424  , bool SO1 // Storage order of the left-hand side dense matrix
425  , typename MT2 // Type of the right-hand side matrix
426  , bool SO2 > // Storage order of the right-hand side matrix
427 inline auto smpSubAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
428  -> EnableIf_t< IsDenseMatrix_v<MT1> && ( !IsSMPAssignable_v<MT1> || !IsSMPAssignable_v<MT2> ) >
429 {
431 
432  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
433  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
434 
435  subAssign( ~lhs, ~rhs );
436 }
438 //*************************************************************************************************
439 
440 
441 //*************************************************************************************************
459 template< typename MT1 // Type of the left-hand side dense matrix
460  , bool SO1 // Storage order of the left-hand side dense matrix
461  , typename MT2 // Type of the right-hand side matrix
462  , bool SO2 > // Storage order of the right-hand side matrix
463 inline auto smpSubAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
464  -> EnableIf_t< IsDenseMatrix_v<MT1> && IsSMPAssignable_v<MT1> && IsSMPAssignable_v<MT2> >
465 {
467 
468  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT1> );
469  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT2> );
470 
471  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
472  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
473 
474  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
475  subAssign( ~lhs, ~rhs );
476  }
477  else {
478  hpxAssign( ~lhs, ~rhs, []( auto& a, const auto& b ){ subAssign( a, b ); } );
479  }
480 }
482 //*************************************************************************************************
483 
484 
485 
486 
487 //=================================================================================================
488 //
489 // SCHUR PRODUCT ASSIGNMENT
490 //
491 //=================================================================================================
492 
493 //*************************************************************************************************
511 template< typename MT1 // Type of the left-hand side dense matrix
512  , bool SO1 // Storage order of the left-hand side dense matrix
513  , typename MT2 // Type of the right-hand side matrix
514  , bool SO2 > // Storage order of the right-hand side matrix
515 inline auto smpSchurAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
516  -> EnableIf_t< IsDenseMatrix_v<MT1> && ( !IsSMPAssignable_v<MT1> || !IsSMPAssignable_v<MT2> ) >
517 {
519 
520  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
521  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
522 
523  schurAssign( ~lhs, ~rhs );
524 }
526 //*************************************************************************************************
527 
528 
529 //*************************************************************************************************
547 template< typename MT1 // Type of the left-hand side dense matrix
548  , bool SO1 // Storage order of the left-hand side dense matrix
549  , typename MT2 // Type of the right-hand side matrix
550  , bool SO2 > // Storage order of the right-hand side matrix
551 inline auto smpSchurAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
552  -> EnableIf_t< IsDenseMatrix_v<MT1> && IsSMPAssignable_v<MT1> && IsSMPAssignable_v<MT2> >
553 {
555 
556  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT1> );
557  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<MT2> );
558 
559  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
560  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
561 
562  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
563  schurAssign( ~lhs, ~rhs );
564  }
565  else {
566  hpxAssign( ~lhs, ~rhs, []( auto& a, const auto& b ){ schurAssign( a, b ); } );
567  }
568 }
570 //*************************************************************************************************
571 
572 
573 
574 
575 //=================================================================================================
576 //
577 // MULTIPLICATION ASSIGNMENT
578 //
579 //=================================================================================================
580 
581 //*************************************************************************************************
597 template< typename MT1 // Type of the left-hand side dense matrix
598  , bool SO1 // Storage order of the left-hand side matrix
599  , typename MT2 // Type of the right-hand side matrix
600  , bool SO2 > // Storage order of the right-hand side matrix
601 inline auto smpMultAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
602  -> EnableIf_t< IsDenseMatrix_v<MT1> >
603 {
605 
606  BLAZE_INTERNAL_ASSERT( (~lhs).rows() == (~rhs).rows() , "Invalid number of rows" );
607  BLAZE_INTERNAL_ASSERT( (~lhs).columns() == (~rhs).columns(), "Invalid number of columns" );
608 
609  multAssign( ~lhs, ~rhs );
610 }
612 //*************************************************************************************************
613 
614 
615 
616 
617 //=================================================================================================
618 //
619 // COMPILE TIME CONSTRAINT
620 //
621 //=================================================================================================
622 
623 //*************************************************************************************************
625 namespace {
626 
628 
629 }
631 //*************************************************************************************************
632 
633 } // namespace blaze
634 
635 #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 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
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.
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
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,...
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.