Blaze 3.9
DenseVector.h
Go to the documentation of this file.
1//=================================================================================================
33//=================================================================================================
34
35#ifndef _BLAZE_MATH_SMP_OPENMP_DENSEVECTOR_H_
36#define _BLAZE_MATH_SMP_OPENMP_DENSEVECTOR_H_
37
38
39//*************************************************************************************************
40// Includes
41//*************************************************************************************************
42
43#include <omp.h>
44#include <blaze/math/Aliases.h>
56#include <blaze/system/SMP.h>
58#include <blaze/util/Assert.h>
59#include <blaze/util/EnableIf.h>
62#include <blaze/util/Types.h>
63
64
65namespace blaze {
66
67//=================================================================================================
68//
69// OPENMP-BASED ASSIGNMENT KERNELS
70//
71//=================================================================================================
72
73//*************************************************************************************************
90template< typename VT1 // Type of the left-hand side dense vector
91 , bool TF1 // Transpose flag of the left-hand side dense vector
92 , typename VT2 // Type of the right-hand side dense vector
93 , bool TF2 // Transpose flag of the right-hand side dense vector
94 , typename OP > // Type of the assignment operation
95void openmpAssign( DenseVector<VT1,TF1>& lhs, const DenseVector<VT2,TF2>& rhs, OP op )
96{
98
99 BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
100
101 using ET1 = ElementType_t<VT1>;
102 using ET2 = ElementType_t<VT2>;
103
104 constexpr bool simdEnabled( VT1::simdEnabled && VT2::simdEnabled && IsSIMDCombinable_v<ET1,ET2> );
105 constexpr size_t SIMDSIZE( SIMDTrait< ElementType_t<VT1> >::size );
106
107 const bool lhsAligned( (*lhs).isAligned() );
108 const bool rhsAligned( (*rhs).isAligned() );
109
110 const int threads ( omp_get_num_threads() );
111 const size_t addon ( ( ( (*lhs).size() % threads ) != 0UL )? 1UL : 0UL );
112 const size_t equalShare ( (*lhs).size() / threads + addon );
113 const size_t rest ( equalShare & ( SIMDSIZE - 1UL ) );
114 const size_t sizePerThread( ( simdEnabled && rest )?( equalShare - rest + SIMDSIZE ):( equalShare ) );
115
116#pragma omp for schedule(dynamic,1) nowait
117 for( int i=0UL; i<threads; ++i )
118 {
119 const size_t index( i*sizePerThread );
120
121 if( index >= (*lhs).size() )
122 continue;
123
124 const size_t size( min( sizePerThread, (*lhs).size() - index ) );
125
126 if( simdEnabled && lhsAligned && rhsAligned ) {
127 auto target( subvector<aligned>( *lhs, index, size, unchecked ) );
128 const auto source( subvector<aligned>( *rhs, index, size, unchecked ) );
129 op( target, source );
130 }
131 else if( simdEnabled && lhsAligned ) {
132 auto target( subvector<aligned>( *lhs, index, size, unchecked ) );
133 const auto source( subvector<unaligned>( *rhs, index, size, unchecked ) );
134 op( target, source );
135 }
136 else if( simdEnabled && rhsAligned ) {
137 auto target( subvector<unaligned>( *lhs, index, size, unchecked ) );
138 const auto source( subvector<aligned>( *rhs, index, size, unchecked ) );
139 op( target, source );
140 }
141 else {
142 auto target( subvector<unaligned>( *lhs, index, size, unchecked ) );
143 const auto source( subvector<unaligned>( *rhs, index, size, unchecked ) );
144 op( target, source );
145 }
146 }
147}
149//*************************************************************************************************
150
151
152//*************************************************************************************************
169template< typename VT1 // Type of the left-hand side dense vector
170 , bool TF1 // Transpose flag of the left-hand side dense vector
171 , typename VT2 // Type of the right-hand side sparse vector
172 , bool TF2 // Transpose flag of the right-hand side sparse vector
173 , typename OP > // Type of the assignment operation
174void openmpAssign( DenseVector<VT1,TF1>& lhs, const SparseVector<VT2,TF2>& rhs, OP op )
175{
177
178 BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
179
180 const int threads ( omp_get_num_threads() );
181 const size_t addon ( ( ( (*lhs).size() % threads ) != 0UL )? 1UL : 0UL );
182 const size_t sizePerThread( (*lhs).size() / threads + addon );
183
184#pragma omp for schedule(dynamic,1) nowait
185 for( int i=0UL; i<threads; ++i )
186 {
187 const size_t index( i*sizePerThread );
188
189 if( index >= (*lhs).size() )
190 continue;
191
192 const size_t size( min( sizePerThread, (*lhs).size() - index ) );
193 auto target( subvector<unaligned>( *lhs, index, size, unchecked ) );
194 const auto source( subvector<unaligned>( *rhs, index, size, unchecked ) );
195 op( target, source );
196 }
197}
199//*************************************************************************************************
200
201
202
203
204//=================================================================================================
205//
206// PLAIN ASSIGNMENT
207//
208//=================================================================================================
209
210//*************************************************************************************************
228template< typename VT1 // Type of the left-hand side dense vector
229 , bool TF1 // Transpose flag of the left-hand side dense vector
230 , typename VT2 // Type of the right-hand side vector
231 , bool TF2 > // Transpose flag of the right-hand side vector
232inline auto smpAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
233 -> EnableIf_t< IsDenseVector_v<VT1> && ( !IsSMPAssignable_v<VT1> || !IsSMPAssignable_v<VT2> ) >
234{
236
237 BLAZE_INTERNAL_ASSERT( (*lhs).size() == (*rhs).size(), "Invalid vector sizes" );
238
239 assign( *lhs, *rhs );
240}
242//*************************************************************************************************
243
244
245//*************************************************************************************************
263template< typename VT1 // Type of the left-hand side dense vector
264 , bool TF1 // Transpose flag of the left-hand side dense vector
265 , typename VT2 // Type of the right-hand side vector
266 , bool TF2 > // Transpose flag of the right-hand side vector
267inline auto smpAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
268 -> EnableIf_t< IsDenseVector_v<VT1> && IsSMPAssignable_v<VT1> && IsSMPAssignable_v<VT2> >
269{
271
274
275 BLAZE_INTERNAL_ASSERT( (*lhs).size() == (*rhs).size(), "Invalid vector sizes" );
276
278 {
279 if( isSerialSectionActive() || !(*rhs).canSMPAssign() ) {
280 assign( *lhs, *rhs );
281 }
282 else {
283#pragma omp parallel shared( lhs, rhs )
284 openmpAssign( *lhs, *rhs, []( auto& a, const auto& b ){ assign( a, b ); } );
285 }
286 }
287}
289//*************************************************************************************************
290
291
292
293
294//=================================================================================================
295//
296// ADDITION ASSIGNMENT
297//
298//=================================================================================================
299
300//*************************************************************************************************
318template< typename VT1 // Type of the left-hand side dense vector
319 , bool TF1 // Transpose flag of the left-hand side dense vector
320 , typename VT2 // Type of the right-hand side vector
321 , bool TF2 > // Transpose flag of the right-hand side vector
322inline auto smpAddAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
323 -> EnableIf_t< IsDenseVector_v<VT1> && ( !IsSMPAssignable_v<VT1> || !IsSMPAssignable_v<VT2> ) >
324{
326
327 BLAZE_INTERNAL_ASSERT( (*lhs).size() == (*rhs).size(), "Invalid vector sizes" );
328
329 addAssign( *lhs, *rhs );
330}
332//*************************************************************************************************
333
334
335//*************************************************************************************************
353template< typename VT1 // Type of the left-hand side dense vector
354 , bool TF1 // Transpose flag of the left-hand side dense vector
355 , typename VT2 // Type of the right-hand side vector
356 , bool TF2 > // Transpose flag of the right-hand side vector
357inline auto smpAddAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
358 -> EnableIf_t< IsDenseVector_v<VT1> && IsSMPAssignable_v<VT1> && IsSMPAssignable_v<VT2> >
359{
361
364
365 BLAZE_INTERNAL_ASSERT( (*lhs).size() == (*rhs).size(), "Invalid vector sizes" );
366
368 {
369 if( isSerialSectionActive() || !(*rhs).canSMPAssign() ) {
370 addAssign( *lhs, *rhs );
371 }
372 else {
373#pragma omp parallel shared( lhs, rhs )
374 openmpAssign( *lhs, *rhs, []( auto& a, const auto& b ){ addAssign( a, b ); } );
375 }
376 }
377}
379//*************************************************************************************************
380
381
382
383
384//=================================================================================================
385//
386// SUBTRACTION ASSIGNMENT
387//
388//=================================================================================================
389
390//*************************************************************************************************
408template< typename VT1 // Type of the left-hand side dense vector
409 , bool TF1 // Transpose flag of the left-hand side dense vector
410 , typename VT2 // Type of the right-hand side vector
411 , bool TF2 > // Transpose flag of the right-hand side vector
412inline auto smpSubAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
413 -> EnableIf_t< IsDenseVector_v<VT1> && ( !IsSMPAssignable_v<VT1> || !IsSMPAssignable_v<VT2> ) >
414{
416
417 BLAZE_INTERNAL_ASSERT( (*lhs).size() == (*rhs).size(), "Invalid vector sizes" );
418
419 subAssign( *lhs, *rhs );
420}
422//*************************************************************************************************
423
424
425//*************************************************************************************************
443template< typename VT1 // Type of the left-hand side dense vector
444 , bool TF1 // Transpose flag of the left-hand side dense vector
445 , typename VT2 // Type of the right-hand side vector
446 , bool TF2 > // Transpose flag of the right-hand side vector
447inline auto smpSubAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
448 -> EnableIf_t< IsDenseVector_v<VT1> && IsSMPAssignable_v<VT1> && IsSMPAssignable_v<VT2> >
449{
451
454
455 BLAZE_INTERNAL_ASSERT( (*lhs).size() == (*rhs).size(), "Invalid vector sizes" );
456
458 {
459 if( isSerialSectionActive() || !(*rhs).canSMPAssign() ) {
460 subAssign( *lhs, *rhs );
461 }
462 else {
463#pragma omp parallel shared( lhs, rhs )
464 openmpAssign( *lhs, *rhs, []( auto& a, const auto& b ){ subAssign( a, b ); } );
465 }
466 }
467}
469//*************************************************************************************************
470
471
472
473
474//=================================================================================================
475//
476// MULTIPLICATION ASSIGNMENT
477//
478//=================================================================================================
479
480//*************************************************************************************************
498template< typename VT1 // Type of the left-hand side dense vector
499 , bool TF1 // Transpose flag of the left-hand side dense vector
500 , typename VT2 // Type of the right-hand side vector
501 , bool TF2 > // Transpose flag of the right-hand side vector
502inline auto smpMultAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
503 -> EnableIf_t< IsDenseVector_v<VT1> && ( !IsSMPAssignable_v<VT1> || !IsSMPAssignable_v<VT2> ) >
504{
506
507 BLAZE_INTERNAL_ASSERT( (*lhs).size() == (*rhs).size(), "Invalid vector sizes" );
508
509 multAssign( *lhs, *rhs );
510}
512//*************************************************************************************************
513
514
515//*************************************************************************************************
533template< typename VT1 // Type of the left-hand side dense vector
534 , bool TF1 // Transpose flag of the left-hand side dense vector
535 , typename VT2 // Type of the right-hand side vector
536 , bool TF2 > // Transpose flag of the right-hand side vector
537inline auto smpMultAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
538 -> EnableIf_t< IsDenseVector_v<VT1> && IsSMPAssignable_v<VT1> && IsSMPAssignable_v<VT2> >
539{
541
544
545 BLAZE_INTERNAL_ASSERT( (*lhs).size() == (*rhs).size(), "Invalid vector sizes" );
546
548 {
549 if( isSerialSectionActive() || !(*rhs).canSMPAssign() ) {
550 multAssign( *lhs, *rhs );
551 }
552 else {
553#pragma omp parallel shared( lhs, rhs )
554 openmpAssign( *lhs, *rhs, []( auto& a, const auto& b ){ multAssign( a, b ); } );
555 }
556 }
557}
559//*************************************************************************************************
560
561
562
563
564//=================================================================================================
565//
566// DIVISION ASSIGNMENT
567//
568//=================================================================================================
569
570//*************************************************************************************************
588template< typename VT1 // Type of the left-hand side dense vector
589 , bool TF1 // Transpose flag of the left-hand side dense vector
590 , typename VT2 // Type of the right-hand side vector
591 , bool TF2 > // Transpose flag of the right-hand side vector
592inline auto smpDivAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
593 -> EnableIf_t< IsDenseVector_v<VT1> && ( !IsSMPAssignable_v<VT1> || !IsSMPAssignable_v<VT2> ) >
594{
596
597 BLAZE_INTERNAL_ASSERT( (*lhs).size() == (*rhs).size(), "Invalid vector sizes" );
598
599 divAssign( *lhs, *rhs );
600}
602//*************************************************************************************************
603
604
605//*************************************************************************************************
623template< typename VT1 // Type of the left-hand side dense vector
624 , bool TF1 // Transpose flag of the left-hand side dense vector
625 , typename VT2 // Type of the right-hand side vector
626 , bool TF2 > // Transpose flag of the right-hand side vector
627inline auto smpDivAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
628 -> EnableIf_t< IsDenseVector_v<VT1> && IsSMPAssignable_v<VT1> && IsSMPAssignable_v<VT2> >
629{
631
634
635 BLAZE_INTERNAL_ASSERT( (*lhs).size() == (*rhs).size(), "Invalid vector sizes" );
636
638 {
639 if( isSerialSectionActive() || !(*rhs).canSMPAssign() ) {
640 divAssign( *lhs, *rhs );
641 }
642 else {
643#pragma omp parallel shared( lhs, rhs )
644 openmpAssign( *lhs, *rhs, []( auto& a, const auto& b ){ divAssign( a, b ); } );
645 }
646 }
647}
649//*************************************************************************************************
650
651
652
653
654//=================================================================================================
655//
656// COMPILE TIME CONSTRAINTS
657//
658//=================================================================================================
659
660//*************************************************************************************************
662namespace {
663
665
666}
668//*************************************************************************************************
669
670} // namespace blaze
671
672#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 IsDenseVector type trait.
Header file for the IsSIMDCombinable type trait.
Header file for the IsSMPAssignable type trait.
Deactivation of problematic macros.
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 DenseVector base class.
Header file for the SparseVector base class.
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
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.
Definition: Assert.h:101
auto smpDivAssign(Vector< VT1, TF1 > &lhs, const Vector< VT2, TF2 > &rhs) -> EnableIf_t< IsDenseVector_v< VT1 > >
Default implementation of the SMP division assignment of a vector to a dense vector.
Definition: DenseVector.h:221
bool isParallelSectionActive()
Returns whether a parallel section is active or not.
Definition: ParallelSection.h:221
auto smpAssign(Vector< VT1, TF1 > &lhs, const Vector< VT2, TF2 > &rhs) -> EnableIf_t< IsDenseVector_v< VT1 > >
Default implementation of the SMP assignment of a vector to a dense vector.
Definition: DenseVector.h:105
auto smpAddAssign(Vector< VT1, TF1 > &lhs, const Vector< VT2, TF2 > &rhs) -> EnableIf_t< IsDenseVector_v< VT1 > >
Default implementation of the SMP addition assignment of a vector to a dense vector.
Definition: DenseVector.h:134
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
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 smpSubAssign(Vector< VT1, TF1 > &lhs, const Vector< VT2, TF2 > &rhs) -> EnableIf_t< IsDenseVector_v< VT1 > >
Default implementation of the SMP subtraction assignment of a vector to a dense vector.
Definition: DenseVector.h:163
#define BLAZE_STATIC_ASSERT(expr)
Compile time assertion macro.
Definition: StaticAssert.h:112
#define BLAZE_OPENMP_PARALLEL_MODE
Compilation switch for the OpenMP parallelization.
Definition: SMP.h:68
#define BLAZE_FUNCTION_TRACE
Function trace macro.
Definition: FunctionTrace.h:94
constexpr Unchecked unchecked
Global Unchecked instance.
Definition: Check.h:146
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 Subvector view.