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>
60 #include <blaze/system/SMP.h>
62 #include <blaze/util/Assert.h>
63 #include <blaze/util/EnableIf.h>
65 #include <blaze/util/mpl/And.h>
66 #include <blaze/util/mpl/Not.h>
67 #include <blaze/util/mpl/Or.h>
69 #include <blaze/util/Types.h>
70 
71 
72 namespace blaze {
73 
74 //=================================================================================================
75 //
76 // OPENMP-BASED ASSIGNMENT KERNELS
77 //
78 //=================================================================================================
79 
80 //*************************************************************************************************
97 template< typename VT1 // Type of the left-hand side dense vector
98  , bool TF1 // Transpose flag of the left-hand side dense vector
99  , typename VT2 // Type of the right-hand side dense vector
100  , bool TF2 // Transpose flag of the right-hand side dense vector
101  , typename OP > // Type of the assignment operation
102 void openmpAssign( DenseVector<VT1,TF1>& lhs, const DenseVector<VT2,TF2>& rhs, OP op )
103 {
105 
106  BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
107 
108  using ET1 = ElementType_<VT1>;
109  using ET2 = ElementType_<VT2>;
110 
111  constexpr bool simdEnabled( VT1::simdEnabled && VT2::simdEnabled && IsSIMDCombinable<ET1,ET2>::value );
112  constexpr size_t SIMDSIZE( SIMDTrait< ElementType_<VT1> >::size );
113 
114  const bool lhsAligned( (~lhs).isAligned() );
115  const bool rhsAligned( (~rhs).isAligned() );
116 
117  const int threads ( omp_get_num_threads() );
118  const size_t addon ( ( ( (~lhs).size() % threads ) != 0UL )? 1UL : 0UL );
119  const size_t equalShare ( (~lhs).size() / threads + addon );
120  const size_t rest ( equalShare & ( SIMDSIZE - 1UL ) );
121  const size_t sizePerThread( ( simdEnabled && rest )?( equalShare - rest + SIMDSIZE ):( equalShare ) );
122 
123 #pragma omp for schedule(dynamic,1) nowait
124  for( int i=0UL; i<threads; ++i )
125  {
126  const size_t index( i*sizePerThread );
127 
128  if( index >= (~lhs).size() )
129  continue;
130 
131  const size_t size( min( sizePerThread, (~lhs).size() - index ) );
132 
133  if( simdEnabled && lhsAligned && rhsAligned ) {
134  auto target( subvector<aligned>( ~lhs, index, size, unchecked ) );
135  const auto source( subvector<aligned>( ~rhs, index, size, unchecked ) );
136  op( target, source );
137  }
138  else if( simdEnabled && lhsAligned ) {
139  auto target( subvector<aligned>( ~lhs, index, size, unchecked ) );
140  const auto source( subvector<unaligned>( ~rhs, index, size, unchecked ) );
141  op( target, source );
142  }
143  else if( simdEnabled && rhsAligned ) {
144  auto target( subvector<unaligned>( ~lhs, index, size, unchecked ) );
145  const auto source( subvector<aligned>( ~rhs, index, size, unchecked ) );
146  op( target, source );
147  }
148  else {
149  auto target( subvector<unaligned>( ~lhs, index, size, unchecked ) );
150  const auto source( subvector<unaligned>( ~rhs, index, size, unchecked ) );
151  op( target, source );
152  }
153  }
154 }
156 //*************************************************************************************************
157 
158 
159 //*************************************************************************************************
176 template< typename VT1 // Type of the left-hand side dense vector
177  , bool TF1 // Transpose flag of the left-hand side dense vector
178  , typename VT2 // Type of the right-hand side sparse vector
179  , bool TF2 // Transpose flag of the right-hand side sparse vector
180  , typename OP > // Type of the assignment operation
181 void openmpAssign( DenseVector<VT1,TF1>& lhs, const SparseVector<VT2,TF2>& rhs, OP op )
182 {
184 
185  BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
186 
187  const int threads ( omp_get_num_threads() );
188  const size_t addon ( ( ( (~lhs).size() % threads ) != 0UL )? 1UL : 0UL );
189  const size_t sizePerThread( (~lhs).size() / threads + addon );
190 
191 #pragma omp for schedule(dynamic,1) nowait
192  for( int i=0UL; i<threads; ++i )
193  {
194  const size_t index( i*sizePerThread );
195 
196  if( index >= (~lhs).size() )
197  continue;
198 
199  const size_t size( min( sizePerThread, (~lhs).size() - index ) );
200  auto target( subvector<unaligned>( ~lhs, index, size, unchecked ) );
201  const auto source( subvector<unaligned>( ~rhs, index, size, unchecked ) );
202  op( target, source );
203  }
204 }
206 //*************************************************************************************************
207 
208 
209 
210 
211 //=================================================================================================
212 //
213 // PLAIN ASSIGNMENT
214 //
215 //=================================================================================================
216 
217 //*************************************************************************************************
235 template< typename VT1 // Type of the left-hand side dense vector
236  , bool TF1 // Transpose flag of the left-hand side dense vector
237  , typename VT2 // Type of the right-hand side vector
238  , bool TF2 > // Transpose flag of the right-hand side vector
239 inline EnableIf_< And< IsDenseVector<VT1>
240  , Or< Not< IsSMPAssignable<VT1> >
241  , Not< IsSMPAssignable<VT2> > > > >
242  smpAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
243 {
245 
246  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
247 
248  assign( ~lhs, ~rhs );
249 }
251 //*************************************************************************************************
252 
253 
254 //*************************************************************************************************
272 template< typename VT1 // Type of the left-hand side dense vector
273  , bool TF1 // Transpose flag of the left-hand side dense vector
274  , typename VT2 // Type of the right-hand side vector
275  , bool TF2 > // Transpose flag of the right-hand side vector
276 inline EnableIf_< And< IsDenseVector<VT1>, IsSMPAssignable<VT1>, IsSMPAssignable<VT2> > >
277  smpAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
278 {
280 
281  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT1> );
282  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT2> );
283 
284  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
285 
287  {
288  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
289  assign( ~lhs, ~rhs );
290  }
291  else {
292 #pragma omp parallel shared( lhs, rhs )
293  openmpAssign( ~lhs, ~rhs, Assign() );
294  }
295  }
296 }
298 //*************************************************************************************************
299 
300 
301 
302 
303 //=================================================================================================
304 //
305 // ADDITION ASSIGNMENT
306 //
307 //=================================================================================================
308 
309 //*************************************************************************************************
327 template< typename VT1 // Type of the left-hand side dense vector
328  , bool TF1 // Transpose flag of the left-hand side dense vector
329  , typename VT2 // Type of the right-hand side vector
330  , bool TF2 > // Transpose flag of the right-hand side vector
331 inline EnableIf_< And< IsDenseVector<VT1>
332  , Or< Not< IsSMPAssignable<VT1> >
333  , Not< IsSMPAssignable<VT2> > > > >
334  smpAddAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
335 {
337 
338  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
339 
340  addAssign( ~lhs, ~rhs );
341 }
343 //*************************************************************************************************
344 
345 
346 //*************************************************************************************************
364 template< typename VT1 // Type of the left-hand side dense vector
365  , bool TF1 // Transpose flag of the left-hand side dense vector
366  , typename VT2 // Type of the right-hand side vector
367  , bool TF2 > // Transpose flag of the right-hand side vector
368 inline EnableIf_< And< IsDenseVector<VT1>, IsSMPAssignable<VT1>, IsSMPAssignable<VT2> > >
369  smpAddAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
370 {
372 
373  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT1> );
374  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT2> );
375 
376  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
377 
379  {
380  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
381  addAssign( ~lhs, ~rhs );
382  }
383  else {
384 #pragma omp parallel shared( lhs, rhs )
385  openmpAssign( ~lhs, ~rhs, AddAssign() );
386  }
387  }
388 }
390 //*************************************************************************************************
391 
392 
393 
394 
395 //=================================================================================================
396 //
397 // SUBTRACTION ASSIGNMENT
398 //
399 //=================================================================================================
400 
401 //*************************************************************************************************
419 template< typename VT1 // Type of the left-hand side dense vector
420  , bool TF1 // Transpose flag of the left-hand side dense vector
421  , typename VT2 // Type of the right-hand side vector
422  , bool TF2 > // Transpose flag of the right-hand side vector
423 inline EnableIf_< And< IsDenseVector<VT1>
424  , Or< Not< IsSMPAssignable<VT1> >
425  , Not< IsSMPAssignable<VT2> > > > >
426  smpSubAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
427 {
429 
430  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
431 
432  subAssign( ~lhs, ~rhs );
433 }
435 //*************************************************************************************************
436 
437 
438 //*************************************************************************************************
456 template< typename VT1 // Type of the left-hand side dense vector
457  , bool TF1 // Transpose flag of the left-hand side dense vector
458  , typename VT2 // Type of the right-hand side vector
459  , bool TF2 > // Transpose flag of the right-hand side vector
460 inline EnableIf_< And< IsDenseVector<VT1>, IsSMPAssignable<VT1>, IsSMPAssignable<VT2> > >
461  smpSubAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
462 {
464 
465  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT1> );
466  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT2> );
467 
468  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
469 
471  {
472  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
473  subAssign( ~lhs, ~rhs );
474  }
475  else {
476 #pragma omp parallel shared( lhs, rhs )
477  openmpAssign( ~lhs, ~rhs, SubAssign() );
478  }
479  }
480 }
482 //*************************************************************************************************
483 
484 
485 
486 
487 //=================================================================================================
488 //
489 // MULTIPLICATION ASSIGNMENT
490 //
491 //=================================================================================================
492 
493 //*************************************************************************************************
511 template< typename VT1 // Type of the left-hand side dense vector
512  , bool TF1 // Transpose flag of the left-hand side dense vector
513  , typename VT2 // Type of the right-hand side vector
514  , bool TF2 > // Transpose flag of the right-hand side vector
515 inline EnableIf_< And< IsDenseVector<VT1>
516  , Or< Not< IsSMPAssignable<VT1> >
517  , Not< IsSMPAssignable<VT2> > > > >
518  smpMultAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
519 {
521 
522  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
523 
524  multAssign( ~lhs, ~rhs );
525 }
527 //*************************************************************************************************
528 
529 
530 //*************************************************************************************************
548 template< typename VT1 // Type of the left-hand side dense vector
549  , bool TF1 // Transpose flag of the left-hand side dense vector
550  , typename VT2 // Type of the right-hand side vector
551  , bool TF2 > // Transpose flag of the right-hand side vector
552 inline EnableIf_< And< IsDenseVector<VT1>, IsSMPAssignable<VT1>, IsSMPAssignable<VT2> > >
553  smpMultAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
554 {
556 
557  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT1> );
558  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT2> );
559 
560  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
561 
563  {
564  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
565  multAssign( ~lhs, ~rhs );
566  }
567  else {
568 #pragma omp parallel shared( lhs, rhs )
569  openmpAssign( ~lhs, ~rhs, MultAssign() );
570  }
571  }
572 }
574 //*************************************************************************************************
575 
576 
577 
578 
579 //=================================================================================================
580 //
581 // DIVISION ASSIGNMENT
582 //
583 //=================================================================================================
584 
585 //*************************************************************************************************
603 template< typename VT1 // Type of the left-hand side dense vector
604  , bool TF1 // Transpose flag of the left-hand side dense vector
605  , typename VT2 // Type of the right-hand side vector
606  , bool TF2 > // Transpose flag of the right-hand side vector
607 inline EnableIf_< And< IsDenseVector<VT1>
608  , Or< Not< IsSMPAssignable<VT1> >
609  , Not< IsSMPAssignable<VT2> > > > >
610  smpDivAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
611 {
613 
614  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
615 
616  divAssign( ~lhs, ~rhs );
617 }
619 //*************************************************************************************************
620 
621 
622 //*************************************************************************************************
640 template< typename VT1 // Type of the left-hand side dense vector
641  , bool TF1 // Transpose flag of the left-hand side dense vector
642  , typename VT2 // Type of the right-hand side vector
643  , bool TF2 > // Transpose flag of the right-hand side vector
644 inline EnableIf_< And< IsDenseVector<VT1>, IsSMPAssignable<VT1>, IsSMPAssignable<VT2> > >
645  smpDivAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
646 {
648 
649  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT1> );
650  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_<VT2> );
651 
652  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
653 
655  {
656  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
657  divAssign( ~lhs, ~rhs );
658  }
659  else {
660 #pragma omp parallel shared( lhs, rhs )
661  openmpAssign( ~lhs, ~rhs, DivAssign() );
662  }
663  }
664 }
666 //*************************************************************************************************
667 
668 
669 
670 
671 //=================================================================================================
672 //
673 // COMPILE TIME CONSTRAINTS
674 //
675 //=================================================================================================
676 
677 //*************************************************************************************************
679 namespace {
680 
682 
683 }
685 //*************************************************************************************************
686 
687 } // namespace blaze
688 
689 #endif
Header file for auxiliary alias declarations.
Headerfile for the generic min algorithm.
Header file for basic type definitions.
Header file for the SparseVector base class.
EnableIf_< IsDenseMatrix< MT1 > > smpSubAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP subtraction assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:164
Header file for the Assign functor.
BLAZE_ALWAYS_INLINE size_t size(const Vector< VT, TF > &vector) noexcept
Returns the current size/dimension of the vector.
Definition: Vector.h:265
constexpr Unchecked unchecked
Global Unchecked instance.The blaze::unchecked instance is an optional token for the creation of view...
Definition: Check.h:138
EnableIf_< IsDenseVector< VT1 > > smpMultAssign(Vector< VT1, TF1 > &lhs, const Vector< VT2, TF2 > &rhs)
Default implementation of the SMP multiplication assignment of a vector to a dense vector...
Definition: DenseVector.h:193
Header file for the AddAssign functor.
Header file for the And class template.
const ElementType_< MT > min(const DenseMatrix< MT, SO > &dm)
Returns the smallest element of the dense matrix.
Definition: DenseMatrix.h:1903
Header file for the DenseVector base class.
Header file for the SIMD trait.
EnableIf_< IsDenseMatrix< MT1 > > smpAddAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP addition assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:133
#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
Header file for the implementation of the Subvector view.
Namespace of the Blaze C++ math library.
Definition: Blaze.h:58
Header file for the SubAssign functor.
Compile time assertion.
System settings for the shared-memory parallelization.
Header file for the IsSMPAssignable type trait.
EnableIf_< IsDenseMatrix< MT1 > > smpAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:102
Header file for the Or class template.
Header file for the Not class template.
Header file for the serial section implementation.
Header file for the parallel section implementation.
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:246
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.
EnableIf_< IsDenseVector< VT1 > > smpDivAssign(Vector< VT1, TF1 > &lhs, const Vector< VT2, TF2 > &rhs)
Default implementation of the SMP division assignment of a vector to a dense vector.
Definition: DenseVector.h:222
#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
Header file for the IsDenseVector type trait.
bool isParallelSectionActive()
Returns whether a parallel section is active or not.
Definition: ParallelSection.h:213
Header file for the MultAssign functor.
#define BLAZE_OPENMP_PARALLEL_MODE
Compilation switch for the OpenMP parallelization.This compilation switch enables/disables the OpenMP...
Definition: SMP.h:67
#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, the program execution is terminated. The BLAZE_INTERNAL_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERTION flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:101
Header file for the DivAssign functor.
Constraint on the data type.
Header file for the function trace functionality.