Skip to content
Snippets Groups Projects
Commit c955776c authored by Christian Engwer's avatar Christian Engwer
Browse files

Merge branch 'feature/vc' into 'master'

add support for vectorization library Vc

This branch adds support for the Vc library, which add support for vectorization, including an abstraction for intrisics.

We have been using in EXA-Dune and I belive that the integration of vectorization support into the core-Dune is something Dune in general can benefit from. A separate branch I'm preparing for ISTL will add support for multiple RHS vectors using vectorization.

The branch collects a set of helper classes which allow to add vectorization support to your code with moderate effort. Mainly this means that we have a couple of utility functions, which work for scalar data types, ranges and SIMD data types alike.

See also: !16, dune-istl!17, dune-geometry!13.

**Note**: This is the followup merge request to !16.  The original was merged accidentially and had to be reverted, see #26.  The branch had to be rebased; if you had checked out an earlier version of feature/vc you may need to take special action to rebase onto the new branch.#


See merge request !81
parents b6b29f94 e954ca0d
No related branches found
No related tags found
1 merge request!81add support for vectorization library Vc
Pipeline #
# Defines the functions to use Vc
#
# Vc is a library for high-level Vectorization support in C++
# see https://github.com/VcDevel/Vc
#
# .. cmake_function:: add_dune_vc_flags
#
# .. cmake_param:: targets
# :positional:
# :single:
# :required:
#
# A list of targets to use VC with.
#
function(add_dune_vc_flags _targets)
if(Vc_FOUND)
foreach(_target ${_targets})
target_link_libraries(${_target} ${Vc_LIBRARIES})
target_compile_options(${_target} PUBLIC ${Vc_ALL_FLAGS})
target_include_directories(${_target} SYSTEM PUBLIC ${Vc_INCLUDE_DIR})
endforeach(_target ${_targets})
endif(Vc_FOUND)
endfunction(add_dune_vc_flags)
if(Vc_FOUND)
dune_register_package_flags(COMPILE_OPTIONS "${Vc_ALL_FLAGS}"
LIBRARIES "${Vc_LIBRARIES}"
INCLUDE_DIRS "${Vc_INCLUDE_DIR}")
endif(Vc_FOUND)
set(HAVE_VC ${Vc_FOUND})
......@@ -5,6 +5,7 @@ install(FILES
AddPTScotchFlags.cmake
AddSuiteSparseFlags.cmake
AddUMFPackFlags.cmake
AddVcFlags.cmake
CheckCXXFeatures.cmake
CheckForPthreads.c
CMakeBuiltinFunctionsDocumentation.cmake
......
......@@ -24,3 +24,8 @@ include(AddGMPFlags)
find_package(Inkscape)
include(UseInkscape)
include(FindMProtect)
# try to find the Vc library
find_package(Vc)
include(AddVcFlags)
set_package_info("Vc" "C++ Vectorization library" "https://github.com/VcDevel/Vc")
......@@ -45,6 +45,9 @@
to facilitate activating and deactivating GMP using compile flags. */
#cmakedefine HAVE_GMP ENABLE_GMP
/* Define to 1 if you have the Vc library. */
#cmakedefine HAVE_VC 1
/* Define to 1 if you have the symbol mprotect. */
#cmakedefine HAVE_MPROTECT 1
......
......@@ -21,6 +21,15 @@
@ingroup Utilities
*/
/**
@defgroup RangeUtilities Range Utilities
@brief Utilities for reduction like operations on ranges
All these reduction operations work for appropriate ranges and scalar values
@ingroup Utilities
*/
/**
@defgroup StringUtilities String Utilities
@brief Utility functions for std::string
......
......@@ -34,6 +34,7 @@ install(FILES
boundschecking.hh
classname.hh
concept.hh
conditional.hh
debugallocator.hh
debugstream.hh
deprecated.hh
......@@ -82,8 +83,10 @@ install(FILES
propertymap.hh
promotiontraits.hh
proxymemberaccess.hh
rangeutilities.hh
reservedvector.hh
shared_ptr.hh
simd.hh
singleton.hh
sllist.hh
stdstreams.hh
......
#ifndef DUNE_COMMON_CONDITIONAL_HH
#define DUNE_COMMON_CONDITIONAL_HH
namespace Dune
{
/** \brief conditional evaluate
sometimes call immediate if, evaluates to
\code
if (b)
return v1;
else
return v2;
\endcode
In contrast to if-then-else the cond function can also be
evaluated for vector valued SIMD data types, see simd.hh.
\param b boolean value
\param v1 value of b==true
\param v2 value of b==false
*/
template<typename T1, typename T2>
const T1 cond(bool b, const T1 & v1, const T2 & v2)
{
return (b ? v1 : v2);
}
} // end namespace Dune
#endif // DUNE_COMMON_CONDITIONAL_HH
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifndef DUNE_COMMON_RANGE_UTILITIES_HH
#define DUNE_COMMON_RANGE_UTILITIES_HH
#include <dune/common/typetraits.hh>
#include <utility>
#include <type_traits>
#include <bitset>
/**
* \file
* \brief Utilities for reduction like operations on ranges
* \author Christian Engwer
*/
/**
* @addtogroup RangeUtilities
* @{
*/
namespace Dune
{
/**
\brief compute the maximum value over a range
overloads for scalar values, and ranges exist
*/
template <typename T,
typename std::enable_if<is_range<T>::value, int>::type = 0>
typename T::value_type
max_value(const T & v) {
using std::max;
typename T::value_type m;
for (const auto & e : v)
m = max(e,m);
return m;
};
template <typename T,
typename std::enable_if<!is_range<T>::value, int>::type = 0>
const T & max_value(const T & v) { return v; };
/**
\brief compute the minimum value over a range
overloads for scalar values, and ranges exist
*/
template <typename T,
typename std::enable_if<is_range<T>::value, int>::type = 0>
typename T::value_type
min_value(const T & v) {
using std::min;
typename T::value_type m;
for (const auto & e : v)
m = min(e,m);
return m;
};
template <typename T,
typename std::enable_if<!is_range<T>::value, int>::type = 0>
T & min_value(const T & v) { return v; };
/**
\brief similar to std::bitset<N>::any() return true, if any entries is true
overloads for scalar values, ranges, and std::bitset<N> exist
*/
template <typename T,
typename std::enable_if<is_range<T>::value, int>::type = 0>
bool any_true(const T & v) {
bool b = false;
for (const auto & e : v)
b = b or bool(e);
return b;
};
template <typename T,
typename std::enable_if<!is_range<T>::value, int>::type = 0>
bool any_true(const T & v) { return v; };
template<std::size_t N>
bool any_true(const std::bitset<N> & b)
{
return b.any();
}
/**
\brief similar to std::bitset<N>::all() return true, if any entries is true
overloads for scalar values, ranges, and std::bitset<N> exist
*/
template <typename T,
typename std::enable_if<is_range<T>::value, int>::type = 0>
bool all_true(const T & v) {
bool b = true;
for (const auto & e : v)
b = b and bool(e);
return b;
};
template <typename T,
typename std::enable_if<!is_range<T>::value, int>::type = 0>
bool all_true(const T & v) { return v; };
template<std::size_t N>
bool all_true(const std::bitset<N> & b)
{
return b.all();
}
}
#endif // DUNE_COMMON_RANGE_UTILITIES_HH
#ifndef DUNE_COMMON_SIMD_HH
#define DUNE_COMMON_SIMD_HH
/**
\file Abstractions for support of dedicated SIMD data types
Libraries like Vc (https://github.com/VcDevel/Vc) add high-level
data types for SIMD (or vectorization) support in C++. Most of
these operations mimic the behavior of a numerical data type. Some
boolean operations can not be implemented in a compatible way to
trivial data types.
This header contains additional abstractions to help writing code
that works with trivial numericaldata types (like double) and Vc
vectorization data types.
See also the conditional.hh and range_utils.hh headers.
*/
#include <dune/common/rangeutilities.hh>
#include <dune/common/conditional.hh>
#if HAVE_VC
#include <Vc/Vc>
#endif
namespace Dune
{
template<typename T>
struct SimdScalarTypeTraits
{
using type = T;
};
template<typename T>
using SimdScalar = typename SimdScalarTypeTraits<T>::type;
#if HAVE_VC
/*
Add Vc specializations for the SimdScalarTypeTraits trais class
*/
template<typename T, typename A>
struct SimdScalarTypeTraits< Vc::Vector<T,A> >
{
using type = T;
};
template<typename T, std::size_t N, typename V, std::size_t M>
struct SimdScalarTypeTraits< Vc::SimdArray<T,N,V,M> >
{
using type = T;
};
#endif // HAVE_VC
#if HAVE_VC
/*
Add Vc specializations for cond(), see conditional.hh
*/
template<typename T, typename A>
Vc::Vector<T,A> cond(const Vc::Mask<T,A> & b,
const Vc::Vector<T,A> & v1,
const Vc::Vector<T,A> & v2)
{
return std::move(Vc::iif(b, v1, v2));
}
template<typename T, std::size_t N, typename V, std::size_t M>
Vc::SimdArray<T,N,V,M> cond(const typename Vc::SimdArray<T,N,V,M>::mask_type & b,
const Vc::SimdArray<T,N,V,M> & v1,
const Vc::SimdArray<T,N,V,M> & v2)
{
return std::move(Vc::iif(b, v1, v2));
}
#endif // HAVE_VC
#if HAVE_VC
/*
Add Vc specializations for several boolean operations, see rangeutitlities.hh:
max_value, min_value, any_true, all_true
*/
template<typename T, typename A>
T max_value(const Vc::Vector<T,A> & v)
{
return v.max();
}
template<typename T, std::size_t N, typename V, std::size_t M>
double max_value(const Vc::SimdArray<T,N,V,M> & v)
{
return v.max();
}
template<typename T, typename A>
T min_value(const Vc::Vector<T,A> & v)
{
return v.min();
}
template<typename T, std::size_t N, typename V, std::size_t M>
double min_value(const Vc::SimdArray<T,N,V,M> & v)
{
return v.min();
}
template<typename T, typename A>
bool any_true(const Vc::Mask<T,A> & v)
{
return Vc::any_of(v);
}
template<typename T, std::size_t N, typename V, std::size_t M>
bool any_true(const Vc::SimdMaskArray<T,N,V,M> & v)
{
return Vc::any_of(v);
}
template<typename T, typename A>
bool all_true(const Vc::Mask<T,A> & v)
{
return Vc::all_of(v);
}
template<typename T, std::size_t N, typename V, std::size_t M>
bool all_true(const Vc::SimdMaskArray<T,N,V,M> & v)
{
return Vc::all_of(v);
}
#endif // HAVE_VC
} // end namespace Dune
#endif // DUNE_COMMON_SIMD_HH
......@@ -395,6 +395,25 @@ namespace Dune
#endif // defined(DOXYGEN) or HAVE_IS_INDEXABLE_SUPPORT
/**
typetrait to check that a class has begin() and end() members
*/
// default version, gets picked if SFINAE fails
template<typename T, typename = void, typename = void>
struct is_range
: public std::false_type
{};
#ifndef DOXYGEN
// version for types with begin() and end()
template<typename T>
struct is_range<T,
decltype(std::declval<T>().begin()),
decltype(std::declval<T>().end())>
: public std::true_type
{};
#endif
namespace detail
{
///
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment