#include <cstring>
#include <vector>
+#if DEAL_II_COMPILER_VECTORIZATION_LEVEL > 0
+#include <emmintrin.h>
+#endif
+
DEAL_II_NAMESPACE_OPEN
*/
void add (const Vector<Number> &V);
- /**
- * Simple vectorized (SIMD) vector addition, equal to the <tt>operator +=</tt>.
- * This function should not be used to add the vector to itself, i.e to
- * multiply the current vector by two.
- *
- * @dealiiOperationIsMultithreaded
- */
- void vectorized_add (const Vector<Number> &V);
/**
* Multiple addition of scaled vectors, i.e. <tt>*this += a*V+b*W</tt>.
* VectorView will access the pointer.
*/
friend class VectorView<Number>;
+
+private:
+
+ /**
+ * Allocate @p v and, if possible, align along 64-byte boundaries.
+ */
+ void initialize_val(const size_type n);
+
+ /**
+ * Free @p val.
+ */
+ void clear_val();
};
/*@}*/
{
if (val)
{
- delete[] val;
+ clear_val();
val=0;
}
}
{
if (n==0)
{
- if (val) delete[] val;
+ if (val) clear_val();
val = 0;
max_vec_size = vec_size = 0;
return;
if (n>max_vec_size)
{
- if (val) delete[] val;
- val = new value_type[n];
+ if (val) clear_val();
+ initialize_val(n);
Assert (val != 0, ExcOutOfMemory());
max_vec_size = n;
};
ar &vec_size &max_vec_size ;
- val = new Number[max_vec_size];
+ initialize_val(max_vec_size);
ar &boost::serialization::make_array(val, max_vec_size);
}
+
+template <typename Number>
+inline
+void
+Vector<Number>::initialize_val(const size_type size)
+{
+#if DEAL_II_COMPILER_VECTORIZATION_LEVEL > 0
+ val = static_cast<Number*>(_mm_malloc (size, 64));
+#else
+ val = static_cast<Number*>(malloc (size));
+#endif
+}
+
+
+
+template <typename Number>
+inline
+void
+Vector<Number>::clear_val()
+{
+#if DEAL_II_COMPILER_VECTORIZATION_LEVEL > 0
+ _mm_free(val);
+#else
+ free(val);
+#endif
+}
+
#endif
{
if (vec_size != 0)
{
- val = new Number[max_vec_size];
+ initialize_val(max_vec_size);
Assert (val != 0, ExcOutOfMemory());
*this = v;
}
{
if (vec_size != 0)
{
- val = new Number[max_vec_size];
+ initialize_val(max_vec_size);
Assert (val != 0, ExcOutOfMemory());
std::copy (v.begin(), v.end(), begin());
}
{
if (vec_size != 0)
{
- val = new Number[max_vec_size];
+ iniatilize_val(max_vec_size);
Assert (val != 0, ExcOutOfMemory());
// get a representation of the vector
{
if (vec_size != 0)
{
- val = new Number[max_vec_size];
+ initialize_val(max_vec_size);
Assert (val != 0, ExcOutOfMemory());
// Copy the distributed vector to
{
if (vec_size != 0)
{
- val = new Number[max_vec_size];
+ initialize_val(max_vec_size);
Assert (val != 0, ExcOutOfMemory());
// get a representation of the vector
Assert (vec_size!=0, ExcEmptyObject());
Assert (vec_size == v.vec_size, ExcDimensionMismatch(vec_size, v.vec_size));
- if (vec_size>internal::Vector::minimum_parallel_grain_size)
- parallel::transform (val,
- val+vec_size,
- v.val,
- val,
- (boost::lambda::_1 + boost::lambda::_2),
- internal::Vector::minimum_parallel_grain_size);
- else if (vec_size > 0)
+ // Vectorization can only be if v is not the current vector otherwise there
+ // will be collision
+ if (&(v.val[0])!=&val[0])
+ {
+#ifndef DEAL_II_WITH_THREADS
+#pragma omp simd
for (size_type i=0; i<vec_size; ++i)
val[i] += v.val[i];
+#else
+ if (vec_size>internal::Vector::minimum_parallel_grain_size)
+ {
+ internal::Vectorization_add_1<Number> vector_add;
+ vector_add.val = val;
+ vector_add.v_val = v.val;
+ tbb::parallel_for (tbb::blocked_range<size_type> (0,
+ vec_size,
+ internal::Vector::minimum_parallel_grain_size),
+ vector_add,
+ tbb::auto_partitioner());
+ }
+ else if (vec_size > 0)
+#pragma omp simd
+ for (size_type i=0; i<vec_size; ++i)
+ val[i] += v.val[i];
+#endif
+ }
+ else
+ {
+ if (vec_size>internal::Vector::minimum_parallel_grain_size)
+ parallel::transform (val,
+ val+vec_size,
+ v.val,
+ val,
+ (boost::lambda::_1 + boost::lambda::_2),
+ internal::Vector::minimum_parallel_grain_size);
+ else if (vec_size > 0)
+ for (size_type i=0; i<vec_size; ++i)
+ val[i] += v.val[i];
+ }
}
}
-template <typename Number>
-void Vector<Number>::vectorized_add (const Vector<Number> &v)
-{
- Assert (vec_size!=0, ExcEmptyObject());
- Assert (vec_size == v.vec_size, ExcDimensionMismatch(vec_size, v.vec_size));
-
-#ifndef DEAL_II_WITH_THREADS
-#pragma omp simd
- for (size_type i=0; i<vec_size; ++i)
- val[i] += v.val[i];
-#else
- if (vec_size>internal::Vector::minimum_parallel_grain_size)
- {
- internal::Vectorization_add_1<Number> vector_add;
- vector_add.val = val;
- vector_add.v_val = v.val;
- tbb::parallel_for (tbb::blocked_range<size_type> (0,
- vec_size,
- internal::Vector::minimum_parallel_grain_size),
- vector_add,
- tbb::auto_partitioner());
- }
- else if (vec_size > 0)
-#pragma omp simd
- for (size_type i=0; i<vec_size; ++i)
- val[i] += v.val[i];
-#endif
-}
-
template <typename Number>
void Vector<Number>::sadd (const Number x,