Blaze  3.6
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>
55 #include <blaze/system/SMP.h>
57 #include <blaze/util/Assert.h>
58 #include <blaze/util/EnableIf.h>
61 #include <blaze/util/Types.h>
62 
63 
64 namespace blaze {
65 
66 //=================================================================================================
67 //
68 // THREAD-BASED ASSIGNMENT KERNELS
69 //
70 //=================================================================================================
71 
72 //*************************************************************************************************
90 template< 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
95 void threadAssign( 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 size_t threads ( TheThreadBackend::size() );
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  for( size_t i=0UL; i<threads; ++i )
117  {
118  const size_t index( i*sizePerThread );
119 
120  if( index >= (~lhs).size() )
121  continue;
122 
123  const size_t size( min( sizePerThread, (~lhs).size() - index ) );
124 
125  if( simdEnabled && lhsAligned && rhsAligned ) {
126  auto target( subvector<aligned>( ~lhs, index, size, unchecked ) );
127  const auto source( subvector<aligned>( ~rhs, index, size, unchecked ) );
128  TheThreadBackend::schedule( target, source, op );
129  }
130  else if( simdEnabled && lhsAligned ) {
131  auto target( subvector<aligned>( ~lhs, index, size, unchecked ) );
132  const auto source( subvector<unaligned>( ~rhs, index, size, unchecked ) );
133  TheThreadBackend::schedule( target, source, op );
134  }
135  else if( simdEnabled && rhsAligned ) {
136  auto target( subvector<unaligned>( ~lhs, index, size, unchecked ) );
137  const auto source( subvector<aligned>( ~rhs, index, size, unchecked ) );
138  TheThreadBackend::schedule( target, source, op );
139  }
140  else {
141  auto target( subvector<unaligned>( ~lhs, index, size, unchecked ) );
142  const auto source( subvector<unaligned>( ~rhs, index, size, unchecked ) );
143  TheThreadBackend::schedule( target, source, op );
144  }
145  }
146 
147  TheThreadBackend::wait();
148 }
150 //*************************************************************************************************
151 
152 
153 //*************************************************************************************************
171 template< typename VT1 // Type of the left-hand side dense vector
172  , bool TF1 // Transpose flag of the left-hand side dense vector
173  , typename VT2 // Type of the right-hand side sparse vector
174  , bool TF2 // Transpose flag of the right-hand side sparse vector
175  , typename OP > // Type of the assignment operation
176 void threadAssign( DenseVector<VT1,TF1>& lhs, const SparseVector<VT2,TF2>& rhs, OP op )
177 {
179 
180  BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" );
181 
182  const size_t threads ( TheThreadBackend::size() );
183  const size_t addon ( ( ( (~lhs).size() % threads ) != 0UL )? 1UL : 0UL );
184  const size_t sizePerThread( (~lhs).size() / threads + addon );
185 
186  for( size_t i=0UL; i<threads; ++i )
187  {
188  const size_t index( i*sizePerThread );
189 
190  if( index >= (~lhs).size() )
191  continue;
192 
193  const size_t size( min( sizePerThread, (~lhs).size() - index ) );
194  auto target( subvector<unaligned>( ~lhs, index, size, unchecked ) );
195  const auto source( subvector<unaligned>( ~rhs, index, size, unchecked ) );
196  TheThreadBackend::schedule( target, source, op );
197  }
198 
199  TheThreadBackend::wait();
200 }
202 //*************************************************************************************************
203 
204 
205 
206 
207 //=================================================================================================
208 //
209 // PLAIN ASSIGNMENT
210 //
211 //=================================================================================================
212 
213 //*************************************************************************************************
231 template< typename VT1 // Type of the left-hand side dense vector
232  , bool TF1 // Transpose flag of the left-hand side dense vector
233  , typename VT2 // Type of the right-hand side vector
234  , bool TF2 > // Transpose flag of the right-hand side vector
235 inline auto smpAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
236  -> EnableIf_t< IsDenseVector_v<VT1> && ( !IsSMPAssignable_v<VT1> || !IsSMPAssignable_v<VT2> ) >
237 {
239 
240  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
241 
242  assign( ~lhs, ~rhs );
243 }
245 //*************************************************************************************************
246 
247 
248 //*************************************************************************************************
266 template< typename VT1 // Type of the left-hand side dense vector
267  , bool TF1 // Transpose flag of the left-hand side dense vector
268  , typename VT2 // Type of the right-hand side vector
269  , bool TF2 > // Transpose flag of the right-hand side vector
270 inline auto smpAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
271  -> EnableIf_t< IsDenseVector_v<VT1> && IsSMPAssignable_v<VT1> && IsSMPAssignable_v<VT2> >
272 {
274 
275  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT1> );
276  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT2> );
277 
278  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
279 
281  {
282  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
283  assign( ~lhs, ~rhs );
284  }
285  else {
286  threadAssign( ~lhs, ~rhs, []( auto& a, const auto& b ){ assign( a, b ); } );
287  }
288  }
289 }
291 //*************************************************************************************************
292 
293 
294 
295 
296 //=================================================================================================
297 //
298 // ADDITION ASSIGNMENT
299 //
300 //=================================================================================================
301 
302 //*************************************************************************************************
321 template< typename VT1 // Type of the left-hand side dense vector
322  , bool TF1 // Transpose flag of the left-hand side dense vector
323  , typename VT2 // Type of the right-hand side vector
324  , bool TF2 > // Transpose flag of the right-hand side vector
325 inline auto smpAddAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
326  -> EnableIf_t< IsDenseVector_v<VT1> && ( !IsSMPAssignable_v<VT1> || !IsSMPAssignable_v<VT2> ) >
327 {
329 
330  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
331 
332  addAssign( ~lhs, ~rhs );
333 }
335 //*************************************************************************************************
336 
337 
338 //*************************************************************************************************
356 template< typename VT1 // Type of the left-hand side dense vector
357  , bool TF1 // Transpose flag of the left-hand side dense vector
358  , typename VT2 // Type of the right-hand side vector
359  , bool TF2 > // Transpose flag of the right-hand side vector
360 inline auto smpAddAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
361  -> EnableIf_t< IsDenseVector_v<VT1> && IsSMPAssignable_v<VT1> && IsSMPAssignable_v<VT2> >
362 {
364 
365  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT1> );
366  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT2> );
367 
368  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
369 
371  {
372  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
373  addAssign( ~lhs, ~rhs );
374  }
375  else {
376  threadAssign( ~lhs, ~rhs, []( auto& a, const auto& b ){ addAssign( a, b ); } );
377  }
378  }
379 }
381 //*************************************************************************************************
382 
383 
384 
385 
386 //=================================================================================================
387 //
388 // SUBTRACTION ASSIGNMENT
389 //
390 //=================================================================================================
391 
392 //*************************************************************************************************
411 template< typename VT1 // Type of the left-hand side dense vector
412  , bool TF1 // Transpose flag of the left-hand side dense vector
413  , typename VT2 // Type of the right-hand side vector
414  , bool TF2 > // Transpose flag of the right-hand side vector
415 inline auto smpSubAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
416  -> EnableIf_t< IsDenseVector_v<VT1> && ( !IsSMPAssignable_v<VT1> || !IsSMPAssignable_v<VT2> ) >
417 {
419 
420  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
421 
422  subAssign( ~lhs, ~rhs );
423 }
425 //*************************************************************************************************
426 
427 
428 //*************************************************************************************************
447 template< typename VT1 // Type of the left-hand side dense vector
448  , bool TF1 // Transpose flag of the left-hand side dense vector
449  , typename VT2 // Type of the right-hand side vector
450  , bool TF2 > // Transpose flag of the right-hand side vector
451 inline auto smpSubAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
452  -> EnableIf_t< IsDenseVector_v<VT1> && IsSMPAssignable_v<VT1> && IsSMPAssignable_v<VT2> >
453 {
455 
456  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT1> );
457  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT2> );
458 
459  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
460 
462  {
463  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
464  subAssign( ~lhs, ~rhs );
465  }
466  else {
467  threadAssign( ~lhs, ~rhs, []( auto& a, const auto& b ){ subAssign( a, b ); } );
468  }
469  }
470 }
472 //*************************************************************************************************
473 
474 
475 
476 
477 //=================================================================================================
478 //
479 // MULTIPLICATION ASSIGNMENT
480 //
481 //=================================================================================================
482 
483 //*************************************************************************************************
502 template< typename VT1 // Type of the left-hand side dense vector
503  , bool TF1 // Transpose flag of the left-hand side dense vector
504  , typename VT2 // Type of the right-hand side vector
505  , bool TF2 > // Transpose flag of the right-hand side vector
506 inline auto smpMultAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
507  -> EnableIf_t< IsDenseVector_v<VT1> && ( !IsSMPAssignable_v<VT1> || !IsSMPAssignable_v<VT2> ) >
508 {
510 
511  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
512 
513  multAssign( ~lhs, ~rhs );
514 }
516 //*************************************************************************************************
517 
518 
519 //*************************************************************************************************
538 template< typename VT1 // Type of the left-hand side dense vector
539  , bool TF1 // Transpose flag of the left-hand side dense vector
540  , typename VT2 // Type of the right-hand side vector
541  , bool TF2 > // Transpose flag of the right-hand side vector
542 inline auto smpMultAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
543  -> EnableIf_t< IsDenseVector_v<VT1> && IsSMPAssignable_v<VT1> && IsSMPAssignable_v<VT2> >
544 {
546 
547  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT1> );
548  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT2> );
549 
550  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
551 
553  {
554  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
555  multAssign( ~lhs, ~rhs );
556  }
557  else {
558  threadAssign( ~lhs, ~rhs, []( auto& a, const auto& b ){ multAssign( a, b ); } );
559  }
560  }
561 }
563 //*************************************************************************************************
564 
565 
566 
567 
568 //=================================================================================================
569 //
570 // DIVISION ASSIGNMENT
571 //
572 //=================================================================================================
573 
574 //*************************************************************************************************
593 template< typename VT1 // Type of the left-hand side dense vector
594  , bool TF1 // Transpose flag of the left-hand side dense vector
595  , typename VT2 // Type of the right-hand side vector
596  , bool TF2 > // Transpose flag of the right-hand side vector
597 inline auto smpDivAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
598  -> EnableIf_t< IsDenseVector_v<VT1> && ( !IsSMPAssignable_v<VT1> || !IsSMPAssignable_v<VT2> ) >
599 {
601 
602  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
603 
604  divAssign( ~lhs, ~rhs );
605 }
607 //*************************************************************************************************
608 
609 
610 //*************************************************************************************************
628 template< typename VT1 // Type of the left-hand side dense vector
629  , bool TF1 // Transpose flag of the left-hand side dense vector
630  , typename VT2 // Type of the right-hand side vector
631  , bool TF2 > // Transpose flag of the right-hand side vector
632 inline auto smpDivAssign( Vector<VT1,TF1>& lhs, const Vector<VT2,TF2>& rhs )
633  -> EnableIf_t< IsDenseVector_v<VT1> && IsSMPAssignable_v<VT1> && IsSMPAssignable_v<VT2> >
634 {
636 
637  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT1> );
638  BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_t<VT2> );
639 
640  BLAZE_INTERNAL_ASSERT( (~lhs).size() == (~rhs).size(), "Invalid vector sizes" );
641 
643  {
644  if( isSerialSectionActive() || !(~rhs).canSMPAssign() ) {
645  divAssign( ~lhs, ~rhs );
646  }
647  else {
648  threadAssign( ~lhs, ~rhs, []( auto& a, const auto& b ){ divAssign( a, b ); } );
649  }
650  }
651 }
653 //*************************************************************************************************
654 
655 
656 
657 
658 //=================================================================================================
659 //
660 // COMPILE TIME CONSTRAINTS
661 //
662 //=================================================================================================
663 
664 //*************************************************************************************************
666 namespace {
667 
669 
670 }
672 //*************************************************************************************************
673 
674 } // namespace blaze
675 
676 #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.
#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 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
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:1162
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
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,...
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
Constraint on the data type.
Header file for the function trace functionality.