DenseVector.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_SMP_THREADS_DENSEVECTOR_H_
36 #define _BLAZE_MATH_SMP_THREADS_DENSEVECTOR_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <blaze/math/Aliases.h>
60 #include <blaze/system/SMP.h>
62 #include <blaze/util/Assert.h>
63 #include <blaze/util/EnableIf.h>
66 #include <blaze/util/Types.h>
67 
68 
69 namespace blaze {
70 
71 //=================================================================================================
72 //
73 // THREAD-BASED ASSIGNMENT KERNELS
74 //
75 //=================================================================================================
76 
77 //*************************************************************************************************
95 template< typename VT1 // Type of the left-hand side dense vector
96  , bool TF1 // Transpose flag of the left-hand side dense vector
97  , typename VT2 // Type of the right-hand side dense vector
98  , bool TF2 // Transpose flag of the right-hand side dense vector
99  , typename OP > // Type of the assignment operation
100 void threadAssign( DenseVector<VT1,TF1>& lhs, const DenseVector<VT2,TF2>& rhs, OP op )
101 {
103 
104  BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
105 
106  using ET1 = ElementType_t<VT1>;
107  using ET2 = ElementType_t<VT2>;
108 
109  constexpr bool simdEnabled( VT1::simdEnabled && VT2::simdEnabled && IsSIMDCombinable_v<ET1,ET2> );
110  constexpr size_t SIMDSIZE( SIMDTrait< ElementType_t<VT1> >::size );
111 
112  const bool lhsAligned( (~lhs).isAligned() );
113  const bool rhsAligned( (~rhs).isAligned() );
114 
115  const size_t threads ( TheThreadBackend::size() );
116  const size_t addon ( ( ( (~lhs).size() % threads ) != 0UL )? 1UL : 0UL );
117  const size_t equalShare ( (~lhs).size() / threads + addon );
118  const size_t rest ( equalShare & ( SIMDSIZE - 1UL ) );
119  const size_t sizePerThread( ( simdEnabled && rest )?( equalShare - rest + SIMDSIZE ):( equalShare ) );
120 
121  for( size_t i=0UL; i<threads; ++i )
122  {
123  const size_t index( i*sizePerThread );
124 
125  if( index >= (~lhs).size() )
126  continue;
127 
128  const size_t size( min( sizePerThread, (~lhs).size() - index ) );
129 
130  if( simdEnabled && lhsAligned && rhsAligned ) {
131  auto target( subvector<aligned>( ~lhs, index, size, unchecked ) );
132  const auto source( subvector<aligned>( ~rhs, index, size, unchecked ) );
133  TheThreadBackend::schedule( target, source, op );
134  }
135  else if( simdEnabled && lhsAligned ) {
136  auto target( subvector<aligned>( ~lhs, index, size, unchecked ) );
137  const auto source( subvector<unaligned>( ~rhs, index, size, unchecked ) );
138  TheThreadBackend::schedule( target, source, op );
139  }
140  else if( simdEnabled && rhsAligned ) {
141  auto target( subvector<unaligned>( ~lhs, index, size, unchecked ) );
142  const auto source( subvector<aligned>( ~rhs, index, size, unchecked ) );
143  TheThreadBackend::schedule( target, source, op );
144  }
145  else {
146  auto target( subvector<unaligned>( ~lhs, index, size, unchecked ) );
147  const auto source( subvector<unaligned>( ~rhs, index, size, unchecked ) );
148  TheThreadBackend::schedule( target, source, op );
149  }
150  }
151 
152  TheThreadBackend::wait();
153 }
155 //*************************************************************************************************
156 
157 
158 //*************************************************************************************************
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 threadAssign( 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 size_t threads ( TheThreadBackend::size() );
188  const size_t addon ( ( ( (~lhs).size() % threads ) != 0UL )? 1UL : 0UL );
189  const size_t sizePerThread( (~lhs).size() / threads + addon );
190 
191  for( size_t i=0UL; i<threads; ++i )
192  {
193  const size_t index( i*sizePerThread );
194 
195  if( index >= (~lhs).size() )
196  continue;
197 
198  const size_t size( min( sizePerThread, (~lhs).size() - index ) );
199  auto target( subvector<unaligned>( ~lhs, index, size, unchecked ) );
200  const auto source( subvector<unaligned>( ~rhs, index, size, unchecked ) );
201  TheThreadBackend::schedule( target, source, op );
202  }
203 
204  TheThreadBackend::wait();
205 }
207 //*************************************************************************************************
208 
209 
210 
211 
212 //=================================================================================================
213 //
214 // PLAIN ASSIGNMENT
215 //
216 //=================================================================================================
217 
218 //*************************************************************************************************
236 template< typename VT1 // Type of the left-hand side dense vector
237  , bool TF1 // Transpose flag of the left-hand side dense vector
238  , typename VT2 // Type of the right-hand side vector
239  , bool TF2 > // Transpose flag of the right-hand side vector
240 inline auto smpAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
241  -> EnableIf_t< IsDenseVector_v<VT1> && ( !IsSMPAssignable_v<VT1> || !IsSMPAssignable_v<VT2> ) >
242 {
244 
245  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
246 
247  assign( ~lhs, ~rhs );
248 }
250 //*************************************************************************************************
251 
252 
253 //*************************************************************************************************
271 template< typename VT1 // Type of the left-hand side dense vector
272  , bool TF1 // Transpose flag of the left-hand side dense vector
273  , typename VT2 // Type of the right-hand side vector
274  , bool TF2 > // Transpose flag of the right-hand side vector
275 inline auto smpAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
276  -> EnableIf_t< IsDenseVector_v<VT1> && IsSMPAssignable_v<VT1> && IsSMPAssignable_v<VT2> >
277 {
279 
280  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT1> );
281  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT2> );
282 
283  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
284 
286  {
287  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
288  assign( ~lhs, ~rhs );
289  }
290  else {
291  threadAssign( ~lhs, ~rhs, Assign() );
292  }
293  }
294 }
296 //*************************************************************************************************
297 
298 
299 
300 
301 //=================================================================================================
302 //
303 // ADDITION ASSIGNMENT
304 //
305 //=================================================================================================
306 
307 //*************************************************************************************************
326 template< typename VT1 // Type of the left-hand side dense vector
327  , bool TF1 // Transpose flag of the left-hand side dense vector
328  , typename VT2 // Type of the right-hand side vector
329  , bool TF2 > // Transpose flag of the right-hand side vector
330 inline auto smpAddAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
331  -> EnableIf_t< IsDenseVector_v<VT1> && ( !IsSMPAssignable_v<VT1> || !IsSMPAssignable_v<VT2> ) >
332 {
334 
335  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
336 
337  addAssign( ~lhs, ~rhs );
338 }
340 //*************************************************************************************************
341 
342 
343 //*************************************************************************************************
361 template< typename VT1 // Type of the left-hand side dense vector
362  , bool TF1 // Transpose flag of the left-hand side dense vector
363  , typename VT2 // Type of the right-hand side vector
364  , bool TF2 > // Transpose flag of the right-hand side vector
365 inline auto smpAddAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
366  -> EnableIf_t< IsDenseVector_v<VT1> && IsSMPAssignable_v<VT1> && IsSMPAssignable_v<VT2> >
367 {
369 
370  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT1> );
371  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT2> );
372 
373  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
374 
376  {
377  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
378  addAssign( ~lhs, ~rhs );
379  }
380  else {
381  threadAssign( ~lhs, ~rhs, AddAssign() );
382  }
383  }
384 }
386 //*************************************************************************************************
387 
388 
389 
390 
391 //=================================================================================================
392 //
393 // SUBTRACTION ASSIGNMENT
394 //
395 //=================================================================================================
396 
397 //*************************************************************************************************
416 template< typename VT1 // Type of the left-hand side dense vector
417  , bool TF1 // Transpose flag of the left-hand side dense vector
418  , typename VT2 // Type of the right-hand side vector
419  , bool TF2 > // Transpose flag of the right-hand side vector
420 inline auto smpSubAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
421  -> EnableIf_t< IsDenseVector_v<VT1> && ( !IsSMPAssignable_v<VT1> || !IsSMPAssignable_v<VT2> ) >
422 {
424 
425  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
426 
427  subAssign( ~lhs, ~rhs );
428 }
430 //*************************************************************************************************
431 
432 
433 //*************************************************************************************************
452 template< typename VT1 // Type of the left-hand side dense vector
453  , bool TF1 // Transpose flag of the left-hand side dense vector
454  , typename VT2 // Type of the right-hand side vector
455  , bool TF2 > // Transpose flag of the right-hand side vector
456 inline auto smpSubAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
457  -> EnableIf_t< IsDenseVector_v<VT1> && IsSMPAssignable_v<VT1> && IsSMPAssignable_v<VT2> >
458 {
460 
461  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT1> );
462  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT2> );
463 
464  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
465 
467  {
468  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
469  subAssign( ~lhs, ~rhs );
470  }
471  else {
472  threadAssign( ~lhs, ~rhs, SubAssign() );
473  }
474  }
475 }
477 //*************************************************************************************************
478 
479 
480 
481 
482 //=================================================================================================
483 //
484 // MULTIPLICATION ASSIGNMENT
485 //
486 //=================================================================================================
487 
488 //*************************************************************************************************
507 template< typename VT1 // Type of the left-hand side dense vector
508  , bool TF1 // Transpose flag of the left-hand side dense vector
509  , typename VT2 // Type of the right-hand side vector
510  , bool TF2 > // Transpose flag of the right-hand side vector
511 inline auto smpMultAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
512  -> EnableIf_t< IsDenseVector_v<VT1> && ( !IsSMPAssignable_v<VT1> || !IsSMPAssignable_v<VT2> ) >
513 {
515 
516  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
517 
518  multAssign( ~lhs, ~rhs );
519 }
521 //*************************************************************************************************
522 
523 
524 //*************************************************************************************************
543 template< typename VT1 // Type of the left-hand side dense vector
544  , bool TF1 // Transpose flag of the left-hand side dense vector
545  , typename VT2 // Type of the right-hand side vector
546  , bool TF2 > // Transpose flag of the right-hand side vector
547 inline auto smpMultAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
548  -> EnableIf_t< IsDenseVector_v<VT1> && IsSMPAssignable_v<VT1> && IsSMPAssignable_v<VT2> >
549 {
551 
552  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT1> );
553  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT2> );
554 
555  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
556 
558  {
559  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
560  multAssign( ~lhs, ~rhs );
561  }
562  else {
563  threadAssign( ~lhs, ~rhs, MultAssign() );
564  }
565  }
566 }
568 //*************************************************************************************************
569 
570 
571 
572 
573 //=================================================================================================
574 //
575 // DIVISION ASSIGNMENT
576 //
577 //=================================================================================================
578 
579 //*************************************************************************************************
598 template< typename VT1 // Type of the left-hand side dense vector
599  , bool TF1 // Transpose flag of the left-hand side dense vector
600  , typename VT2 // Type of the right-hand side vector
601  , bool TF2 > // Transpose flag of the right-hand side vector
602 inline auto smpDivAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
603  -> EnableIf_t< IsDenseVector_v<VT1> && ( !IsSMPAssignable_v<VT1> || !IsSMPAssignable_v<VT2> ) >
604 {
606 
607  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
608 
609  divAssign( ~lhs, ~rhs );
610 }
612 //*************************************************************************************************
613 
614 
615 //*************************************************************************************************
633 template< typename VT1 // Type of the left-hand side dense vector
634  , bool TF1 // Transpose flag of the left-hand side dense vector
635  , typename VT2 // Type of the right-hand side vector
636  , bool TF2 > // Transpose flag of the right-hand side vector
637 inline auto smpDivAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
638  -> EnableIf_t< IsDenseVector_v<VT1> && IsSMPAssignable_v<VT1> && IsSMPAssignable_v<VT2> >
639 {
641 
642  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT1> );
643  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT2> );
644 
645  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
646 
648  {
649  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
650  divAssign( ~lhs, ~rhs );
651  }
652  else {
653  threadAssign( ~lhs, ~rhs, DivAssign() );
654  }
655  }
656 }
658 //*************************************************************************************************
659 
660 
661 
662 
663 //=================================================================================================
664 //
665 // COMPILE TIME CONSTRAINTS
666 //
667 //=================================================================================================
668 
669 //*************************************************************************************************
671 namespace {
672 
674 
675 }
677 //*************************************************************************************************
678 
679 } // namespace blaze
680 
681 #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.
Header file for the Assign functor.
#define BLAZE_BOOST_THREADS_PARALLEL_MODE
Compilation switch for the Boost parallelization.This compilation switch enables/disables the paralle...
Definition: SMP.h:152
constexpr Unchecked unchecked
Global Unchecked instance.The blaze::unchecked instance is an optional token for the creation of view...
Definition: Check.h:138
Header file for the AddAssign functor.
Header file for the DenseVector base class.
Header file for the SIMD trait.
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:220
#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.
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:1147
Header file for the serial section implementation.
#define BLAZE_CPP_THREADS_PARALLEL_MODE
Compilation switch for the C++11 parallelization.This compilation switch enables/disables the paralle...
Definition: SMP.h:124
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:254
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
#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
Header file for the IsDenseVector type trait.
bool isParallelSectionActive()
Returns whether a parallel section is active or not.
Definition: ParallelSection.h:221
Header file for the MultAssign functor.
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 the C++11 and Boost thread backend.
#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
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
Header file for the DivAssign functor.
Constraint on the data type.
Header file for the function trace functionality.