Blaze 3.9
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
67namespace blaze {
68
69//=================================================================================================
70//
71// HPX-BASED ASSIGNMENT KERNELS
72//
73//=================================================================================================
74
75//*************************************************************************************************
92template< 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
97void hpxAssign( DenseMatrix<MT1,SO1>& lhs, const DenseMatrix<MT2,SO2>& rhs, OP op )
98{
99#if HPX_VERSION_FULL < 0x010800
100 using hpx::for_loop;
101 using hpx::execution::par;
102#else
103 using hpx::experimental::for_loop;
104 using hpx::execution::par;
105#endif
106
108
109 using ET1 = ElementType_t<MT1>;
110 using ET2 = ElementType_t<MT2>;
111
112 constexpr bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSIMDCombinable_v<ET1,ET2> );
113 constexpr size_t SIMDSIZE( SIMDTrait< ElementType_t<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//*************************************************************************************************
185template< 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
190void hpxAssign( DenseMatrix<MT1,SO1>& lhs, const SparseMatrix<MT2,SO2>& rhs, OP op )
191{
192#if HPX_VERSION_FULL >= 0x010500
193 using hpx::for_loop;
194 using hpx::execution::par;
195#else
196 using hpx::parallel::for_loop;
197 using hpx::parallel::execution::par;
198#endif
199
201
202 const size_t threads ( getNumThreads() );
203 const ThreadMapping threadmap( createThreadMapping( threads, *rhs ) );
204
205 const size_t addon1 ( ( ( (*rhs).rows() % threadmap.first ) != 0UL )? 1UL : 0UL );
206 const size_t rowsPerThread( (*rhs).rows() / threadmap.first + addon1 );
207
208 const size_t addon2 ( ( ( (*rhs).columns() % threadmap.second ) != 0UL )? 1UL : 0UL );
209 const size_t colsPerThread( (*rhs).columns() / threadmap.second + addon2 );
210
211 for_loop( par, size_t(0), threads, [&](int i)
212 {
213 const size_t row ( ( i / threadmap.second ) * rowsPerThread );
214 const size_t column( ( i % threadmap.second ) * colsPerThread );
215
216 if( row >= (*rhs).rows() || column >= (*rhs).columns() )
217 return;
218
219 const size_t m( min( rowsPerThread, (*lhs).rows() - row ) );
220 const size_t n( min( colsPerThread, (*lhs).columns() - column ) );
221
222 auto target( submatrix<unaligned>( *lhs, row, column, m, n ) );
223 const auto source( submatrix<unaligned>( *rhs, row, column, m, n ) );
224 op( target, source );
225 } );
226}
228//*************************************************************************************************
229
230
231
232
233//=================================================================================================
234//
235// PLAIN ASSIGNMENT
236//
237//=================================================================================================
238
239//*************************************************************************************************
257template< typename MT1 // Type of the left-hand side dense matrix
258 , bool SO1 // Storage order of the left-hand side dense matrix
259 , typename MT2 // Type of the right-hand side matrix
260 , bool SO2 > // Storage order of the right-hand side matrix
261inline auto smpAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
262 -> EnableIf_t< IsDenseMatrix_v<MT1> && ( !IsSMPAssignable_v<MT1> || !IsSMPAssignable_v<MT2> ) >
263{
265
266 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == (*rhs).rows() , "Invalid number of rows" );
267 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).columns(), "Invalid number of columns" );
268
269 assign( *lhs, *rhs );
270}
272//*************************************************************************************************
273
274
275//*************************************************************************************************
293template< typename MT1 // Type of the left-hand side dense matrix
294 , bool SO1 // Storage order of the left-hand side dense matrix
295 , typename MT2 // Type of the right-hand side matrix
296 , bool SO2 > // Storage order of the right-hand side matrix
297inline auto smpAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
298 -> EnableIf_t< IsDenseMatrix_v<MT1> && IsSMPAssignable_v<MT1> && IsSMPAssignable_v<MT2> >
299{
301
304
305 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == (*rhs).rows() , "Invalid number of rows" );
306 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).columns(), "Invalid number of columns" );
307
308 if( isSerialSectionActive() || !(*rhs).canSMPAssign() ) {
309 assign( *lhs, *rhs );
310 }
311 else {
312 hpxAssign( *lhs, *rhs, []( auto& a, const auto& b ){ assign( a, b ); } );
313 }
314}
316//*************************************************************************************************
317
318
319
320
321//=================================================================================================
322//
323// ADDITION ASSIGNMENT
324//
325//=================================================================================================
326
327//*************************************************************************************************
345template< typename MT1 // Type of the left-hand side dense matrix
346 , bool SO1 // Storage order of the left-hand side dense matrix
347 , typename MT2 // Type of the right-hand side matrix
348 , bool SO2 > // Storage order of the right-hand side matrix
349inline auto smpAddAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
350 -> EnableIf_t< IsDenseMatrix_v<MT1> && ( !IsSMPAssignable_v<MT1> || !IsSMPAssignable_v<MT2> ) >
351{
353
354 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == (*rhs).rows() , "Invalid number of rows" );
355 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).columns(), "Invalid number of columns" );
356
357 addAssign( *lhs, *rhs );
358}
360//*************************************************************************************************
361
362
363//*************************************************************************************************
381template< typename MT1 // Type of the left-hand side dense matrix
382 , bool SO1 // Storage order of the left-hand side dense matrix
383 , typename MT2 // Type of the right-hand side matrix
384 , bool SO2 > // Storage order of the right-hand side matrix
385inline auto smpAddAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
386 -> EnableIf_t< IsDenseMatrix_v<MT1> && IsSMPAssignable_v<MT1> && IsSMPAssignable_v<MT2> >
387{
389
392
393 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == (*rhs).rows() , "Invalid number of rows" );
394 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).columns(), "Invalid number of columns" );
395
396 if( isSerialSectionActive() || !(*rhs).canSMPAssign() ) {
397 addAssign( *lhs, *rhs );
398 }
399 else {
400 hpxAssign( *lhs, *rhs, []( auto& a, const auto& b ){ addAssign( a, b ); } );
401 }
402}
404//*************************************************************************************************
405
406
407
408
409//=================================================================================================
410//
411// SUBTRACTION ASSIGNMENT
412//
413//=================================================================================================
414
415//*************************************************************************************************
433template< typename MT1 // Type of the left-hand side dense matrix
434 , bool SO1 // Storage order of the left-hand side dense matrix
435 , typename MT2 // Type of the right-hand side matrix
436 , bool SO2 > // Storage order of the right-hand side matrix
437inline auto smpSubAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
438 -> EnableIf_t< IsDenseMatrix_v<MT1> && ( !IsSMPAssignable_v<MT1> || !IsSMPAssignable_v<MT2> ) >
439{
441
442 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == (*rhs).rows() , "Invalid number of rows" );
443 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).columns(), "Invalid number of columns" );
444
445 subAssign( *lhs, *rhs );
446}
448//*************************************************************************************************
449
450
451//*************************************************************************************************
469template< typename MT1 // Type of the left-hand side dense matrix
470 , bool SO1 // Storage order of the left-hand side dense matrix
471 , typename MT2 // Type of the right-hand side matrix
472 , bool SO2 > // Storage order of the right-hand side matrix
473inline auto smpSubAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
474 -> EnableIf_t< IsDenseMatrix_v<MT1> && IsSMPAssignable_v<MT1> && IsSMPAssignable_v<MT2> >
475{
477
480
481 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == (*rhs).rows() , "Invalid number of rows" );
482 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).columns(), "Invalid number of columns" );
483
484 if( isSerialSectionActive() || !(*rhs).canSMPAssign() ) {
485 subAssign( *lhs, *rhs );
486 }
487 else {
488 hpxAssign( *lhs, *rhs, []( auto& a, const auto& b ){ subAssign( a, b ); } );
489 }
490}
492//*************************************************************************************************
493
494
495
496
497//=================================================================================================
498//
499// SCHUR PRODUCT ASSIGNMENT
500//
501//=================================================================================================
502
503//*************************************************************************************************
521template< typename MT1 // Type of the left-hand side dense matrix
522 , bool SO1 // Storage order of the left-hand side dense matrix
523 , typename MT2 // Type of the right-hand side matrix
524 , bool SO2 > // Storage order of the right-hand side matrix
525inline auto smpSchurAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
526 -> EnableIf_t< IsDenseMatrix_v<MT1> && ( !IsSMPAssignable_v<MT1> || !IsSMPAssignable_v<MT2> ) >
527{
529
530 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == (*rhs).rows() , "Invalid number of rows" );
531 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).columns(), "Invalid number of columns" );
532
533 schurAssign( *lhs, *rhs );
534}
536//*************************************************************************************************
537
538
539//*************************************************************************************************
557template< typename MT1 // Type of the left-hand side dense matrix
558 , bool SO1 // Storage order of the left-hand side dense matrix
559 , typename MT2 // Type of the right-hand side matrix
560 , bool SO2 > // Storage order of the right-hand side matrix
561inline auto smpSchurAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
562 -> EnableIf_t< IsDenseMatrix_v<MT1> && IsSMPAssignable_v<MT1> && IsSMPAssignable_v<MT2> >
563{
565
568
569 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == (*rhs).rows() , "Invalid number of rows" );
570 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).columns(), "Invalid number of columns" );
571
572 if( isSerialSectionActive() || !(*rhs).canSMPAssign() ) {
573 schurAssign( *lhs, *rhs );
574 }
575 else {
576 hpxAssign( *lhs, *rhs, []( auto& a, const auto& b ){ schurAssign( a, b ); } );
577 }
578}
580//*************************************************************************************************
581
582
583
584
585//=================================================================================================
586//
587// MULTIPLICATION ASSIGNMENT
588//
589//=================================================================================================
590
591//*************************************************************************************************
607template< typename MT1 // Type of the left-hand side dense matrix
608 , bool SO1 // Storage order of the left-hand side matrix
609 , typename MT2 // Type of the right-hand side matrix
610 , bool SO2 > // Storage order of the right-hand side matrix
611inline auto smpMultAssign( Matrix<MT1,SO1>& lhs, const Matrix<MT2,SO2>& rhs )
612 -> EnableIf_t< IsDenseMatrix_v<MT1> >
613{
615
616 BLAZE_INTERNAL_ASSERT( (*lhs).rows() == (*rhs).rows() , "Invalid number of rows" );
617 BLAZE_INTERNAL_ASSERT( (*lhs).columns() == (*rhs).columns(), "Invalid number of columns" );
618
619 multAssign( *lhs, *rhs );
620}
622//*************************************************************************************************
623
624
625
626
627//=================================================================================================
628//
629// COMPILE TIME CONSTRAINT
630//
631//=================================================================================================
632
633//*************************************************************************************************
635namespace {
636
638
639}
641//*************************************************************************************************
642
643} // namespace blaze
644
645#endif
Header file for auxiliary alias declarations.
Header file for the alignment flag enumeration.
Header file for run time assertion macros.
Header file for the EnableIf class template.
Header file for the function trace functionality.
Header file for the IsDenseMatrix type trait.
Header file for the IsSIMDCombinable type trait.
Header file for the IsSMPAssignable type trait.
Header file for the SIMD trait.
Constraint on the data type.
Header file for the serial section implementation.
Compile time assertion.
Header file for the SMP thread mapping functionality.
Header file for the DenseMatrix base class.
Header file for the SparseMatrix base class.
decltype(auto) column(Matrix< MT, SO > &matrix, RCAs... args)
Creating a view on a specific column of the given matrix.
Definition: Column.h:137
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:1339
#define BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE(T)
Constraint on the data type.
Definition: SMPAssignable.h:81
constexpr size_t size(const Matrix< MT, SO > &matrix) noexcept
Returns the total number of elements of the matrix.
Definition: Matrix.h:676
decltype(auto) row(Matrix< MT, SO > &, RRAs...)
Creating a view on a specific row of the given matrix.
Definition: Row.h:137
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.
Definition: Assert.h:101
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
BLAZE_ALWAYS_INLINE size_t getNumThreads()
Returns the number of threads used for thread parallel operations.
Definition: Functions.h:77
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 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:192
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
bool isSerialSectionActive()
Returns whether a serial section is active or not.
Definition: SerialSection.h:213
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
#define BLAZE_STATIC_ASSERT(expr)
Compile time assertion macro.
Definition: StaticAssert.h:112
#define BLAZE_HPX_PARALLEL_MODE
Compilation switch for the HPX parallelization.
Definition: SMP.h:96
#define BLAZE_FUNCTION_TRACE
Function trace macro.
Definition: FunctionTrace.h:94
Header file for the matrix storage order types.
Header file for SMP utility functions.
System settings for the shared-memory parallelization.
Header file for basic type definitions.
Header file for the generic min algorithm.
Header file for the implementation of the Submatrix view.