Blaze 3.9
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
66namespace blaze {
67
68//=================================================================================================
69//
70// THREAD-BASED ASSIGNMENT KERNELS
71//
72//=================================================================================================
73
74//*************************************************************************************************
91template< 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
96void 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//*************************************************************************************************
187template< 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
192void 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//*************************************************************************************************
261template< 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
265inline 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//*************************************************************************************************
297template< 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
301inline 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
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//*************************************************************************************************
353template< 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
357inline 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//*************************************************************************************************
389template< 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
393inline 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
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//*************************************************************************************************
445template< 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
449inline 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//*************************************************************************************************
482template< 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
486inline 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
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//*************************************************************************************************
538template< 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
542inline 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//*************************************************************************************************
575template< 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
579inline 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
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//*************************************************************************************************
629template< 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
633inline 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//*************************************************************************************************
657namespace {
658
660
661}
663//*************************************************************************************************
664
665} // namespace blaze
666
667#endif
Header file for auxiliary alias declarations.
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 parallel section implementation.
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 C++11 and Boost thread backend.
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
bool isParallelSectionActive()
Returns whether a parallel section is active or not.
Definition: ParallelSection.h:221
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
#define BLAZE_PARALLEL_SECTION
Section for the debugging of the shared-memory parallelization.
Definition: ParallelSection.h:254
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_CPP_THREADS_PARALLEL_MODE
Compilation switch for the C++11 parallelization.
Definition: SMP.h:124
#define BLAZE_BOOST_THREADS_PARALLEL_MODE
Compilation switch for the Boost parallelization.
Definition: SMP.h:152
#define BLAZE_FUNCTION_TRACE
Function trace macro.
Definition: FunctionTrace.h:94
constexpr Unchecked unchecked
Global Unchecked instance.
Definition: Check.h:146
Header file for the matrix storage order types.
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.