From 8bed3891ccd1da56881d4575934ca9603a6d7cb9 Mon Sep 17 00:00:00 2001 From: Bruno Turcksin Date: Wed, 20 Aug 2014 17:01:26 -0500 Subject: [PATCH] Add the first vectorized add and add flags to use OpenMP SIMD pragmas. --- cmake/setup_compiler_flags_gnu.cmake | 7 ++++ cmake/setup_compiler_flags_intel.cmake | 11 ++++++ cmake/setup_compiler_flags_msvc.cmake | 3 ++ include/deal.II/lac/vector.h | 15 ++++++-- include/deal.II/lac/vector.templates.h | 48 ++++++++++++++++++++++++++ 5 files changed, 81 insertions(+), 3 deletions(-) diff --git a/cmake/setup_compiler_flags_gnu.cmake b/cmake/setup_compiler_flags_gnu.cmake index 6fb9d81ab9..f5017fd2cf 100644 --- a/cmake/setup_compiler_flags_gnu.cmake +++ b/cmake/setup_compiler_flags_gnu.cmake @@ -85,6 +85,13 @@ ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-Wno-long-long") ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-Wno-deprecated") ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-Wno-deprecated-declarations") +# +# OpenMP 4.0 can be used for vectorization. Only the vectorization instructions +# are allowed, the threading must done through TBB. Disable unknown-pragmas +# warning, if OpenMP 4.0 is not supported. +# +ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-fopenmp-simd") +ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-Wno-unkown-pragmas") IF(CMAKE_CXX_COMPILER_ID MATCHES "Clang") # diff --git a/cmake/setup_compiler_flags_intel.cmake b/cmake/setup_compiler_flags_intel.cmake index 33f19fc8fc..4b8080cd5e 100644 --- a/cmake/setup_compiler_flags_intel.cmake +++ b/cmake/setup_compiler_flags_intel.cmake @@ -119,6 +119,7 @@ ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd21") ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd2536") +# # Also disable the following warnings that we frequently # trigger writing dimension independent code: # -w111 statement is unreachable @@ -130,12 +131,22 @@ ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd2536") # that is executed only for one specific dimension # -w280 selector expression is constant # When writing 'switch(dim)' +# ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd111") ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd128") ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd185") ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-wd280") +# +# OpenMP 4.0 can be used for vectorization. Only the vectorization instructions +# are allowed, the threading must done through TBB. Disable unknown-pragmas +# warning, if OpenMP 4.0 is not supported. +# +ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-openmp-simd") +ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "-Wno-unkown-pragmas") + + IF(DEAL_II_STATIC_EXECUTABLE) # diff --git a/cmake/setup_compiler_flags_msvc.cmake b/cmake/setup_compiler_flags_msvc.cmake index 7529844b4b..db7fb77ef8 100644 --- a/cmake/setup_compiler_flags_msvc.cmake +++ b/cmake/setup_compiler_flags_msvc.cmake @@ -45,6 +45,9 @@ ADD_FLAGS(DEAL_II_CXX_FLAGS "/W3") # Globally disable some legacy min and max macros that cause problems: ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "/NOMINMAX") +# Disable warning about unknown pragmas +ENABLE_IF_SUPPORTED(DEAL_II_CXX_FLAGS "/wd4068") + ############################# # # # For Release target: # diff --git a/include/deal.II/lac/vector.h b/include/deal.II/lac/vector.h index 6d41c07df9..59205f0dc2 100644 --- a/include/deal.II/lac/vector.h +++ b/include/deal.II/lac/vector.h @@ -586,7 +586,7 @@ public: Vector &operator -= (const Vector &V); /** - * A collective add operation: This funnction adds a whole set of values + * A collective add operation: This function adds a whole set of values * stored in @p values to the vector components specified by @p indices. */ template @@ -627,11 +627,13 @@ public: void add (const Vector &V); /** - * Simple addition of a multiple of a vector, i.e. *this += a*V. + * Simple vectorized (SIMD) vector addition, equal to the operator +=. + * This function should not be used to add the vector to itself, i.e to + * multiply the current vector by two. * * @dealiiOperationIsMultithreaded */ - void add (const Number a, const Vector &V); + void vectorized_add (const Vector &V); /** * Multiple addition of scaled vectors, i.e. *this += a*V+b*W. @@ -641,6 +643,13 @@ public: void add (const Number a, const Vector &V, const Number b, const Vector &W); + /** + * Simple addition of a multiple of a vector, i.e. *this += a*V. + * + * @dealiiOperationIsMultithreaded + */ + void add (const Number a, const Vector &V); + /** * Scaling and simple vector addition, i.e. *this = s*(*this)+V. * diff --git a/include/deal.II/lac/vector.templates.h b/include/deal.II/lac/vector.templates.h index 881dd58c5c..0289f655b7 100644 --- a/include/deal.II/lac/vector.templates.h +++ b/include/deal.II/lac/vector.templates.h @@ -47,6 +47,8 @@ DEAL_II_NAMESPACE_OPEN namespace internal { + typedef types::global_dof_index size_type; + template bool is_non_negative (const T &t) { @@ -115,6 +117,22 @@ namespace internal Assert (false, ExcMessage ("Can't convert a vector of complex numbers " "into a vector of reals/doubles")); } + +#ifdef DEAL_II_WITH_THREADS + template + struct Vectorization_add_1 + { + Number* val; + Number* v_val; + void operator() (const tbb::blocked_range &range) const + { +#pragma omp simd + for (size_type i=range.begin(); i!=range.end(); ++i) + val[i] += v_val[i]; + } + }; +#endif + } @@ -992,6 +1010,36 @@ void Vector::add (const Number a, const Vector &v, } +template +void Vector::vectorized_add (const Vector &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; iinternal::Vector::minimum_parallel_grain_size) + { + internal::Vectorization_add_1 vector_add; + vector_add.val = val; + vector_add.v_val = v.val; + tbb::parallel_for (tbb::blocked_range (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 void Vector::sadd (const Number x, const Vector &v) -- 2.39.5