Dune Core Modules (2.9.0)

SIMD Abstraction Implementation for Vc

Files

file  vc.hh
 SIMD abstractions for Vc.
 

Detailed Description

This implements the vectorization interface for Vc types, namely Vc::Vector, Vc::Mask, Vc::SimdArray and Vc::SimdMask.

As an application developer, you need to #include <dune/common/simd/vc.hh>. You need to make sure that HAVE_VC is true before doing so:

  • If your program works both in the presence and the absence of Vc, wrap the include in #if HAVE_VC and #endif
  • If you write a unit test, in your CMakeLists.txt use dune_add_test(... CMAKE_GUARD Vc_FOUND)

You also need to make sure that the compiler uses the correct flags and that the linker can find the library. (The compilation flags include one that ensures a name mangling scheme that can distinguish the compiler-intrinsic vector types from non-vector types is used.)

  • Either use add_dune_vc_flags(your_application) in CMakeLists.txt,
  • or use dune_enable_all_packages() in your module's toplevel CMakeLists.txt.

There should be no need to explicitly call find_package(Vc) in your CMakeLists.txt, dune-common already does that. If your module can't live without Vc, you may however want to do something like this in your cmake/modules/YourModuleMacros.cmake:

if(NOT Vc_FOUND)
message(SEND_ERROR "This module requires Vc")
endif(NOT Vc_FOUND)

If you just want to compile dune, and have Vc installed to a location where cmake is not looking by default, you need to add that location to CMAKE_PREFIX_PATH. E.g. pass -DCMAKE_PREFIX_PATH=$VCDIR to cmake, for instance by including that in the variable CMAKE_FLAGS in the options file that you pass to dunecontrol. $VCDIR should be the same directory that you passed in -DCMAKE_INSTALL_PREFIX=... to cmake when you compiled Vc, i.e. Vc's main include file should be found under $VCDIR/include/Vc/Vc, and the library under $VCDIR/lib/libVc.a or similar.

Restrictions

During thorough testing of the Vc abstraction implementation it turned out that certain operations were not supported, or were buggy. This meant that the tests had to be relaxed, and/or some restrictions had to made as to how things must be done through the SIMD abstraction, see Limitations of the Abstraction Layer.

For future reference, here is a detailed list of things that certain Vc types do or don't support. s denotes a scalar object/expression (i.e. of type double or in the case of masks bool). v denotes a vector/mask object/expression. sv means that both scalar and vector arguments are accepted. V denotes a vector/mask type. @ means any applicable operator that is not otherwise listed.

| | Vector | Vector | SimdArray | SimdArray | Masks[4] |
| | <double> AVX | <int> SSE | <double,4> | <int,4> | |
|-------------------------+--------------+-----------+------------+-----------+-----------|
| V v(s); | y | y | y | y | y |
| V v = s; | y | y | y | y | *N* |
| V v{s}; | *N* | y | *N* | *N* | y |
| V v = {s}; | *N* | y | *N* | *N* | *N* |
|-------------------------+--------------+-----------+------------+-----------+-----------|
| v = s; | y | y | y | y | *N* |
| v = {s}; | *N* | *N* | *N* | *N* | *N* |
|-------------------------+--------------+-----------+------------+-----------+-----------|
| v++; ++v; | y | y | *N* | *N* | y(n/a)[2] |
| v--; --v; | y | y | *N* | *N* | n/a |
|-------------------------+--------------+-----------+------------+-----------+-----------|
| +v; -v; | y | y | y | y | *N* |
| !v; | y | y | y | y | y |
| ~v; | n/a | y | n/a | y | *N* |
|-------------------------+--------------+-----------+------------+-----------+-----------|
| sv @ sv; but see below | y | y | y | y | *N* |
|-------------------------+--------------+-----------+------------+-----------+-----------|
| s << v; s >> v; | n/a | *N* | n/a | *N* | *N* |
|-------------------------+--------------+-----------+------------+-----------+-----------|
| v == v; v != v; | y | y | y | y | *N* [1] |
|-------------------------+--------------+-----------+------------+-----------+-----------|
| v & v; v ^ v; v ¦ v; | n/a | y | n/a | y | y |
| sv && sv; sv ¦¦ sv; | y | y | *N* | *N* | *N* |
| v && v; v ¦¦ v; | y | y | *N* | *N* | y |
|-------------------------+--------------+-----------+------------+-----------+-----------|
| v @= sv; but see below | y | y | y | y | *N* |
| v &= v; v ^= v; v ¦= v; | n/a | y | n/a | y | y |
|-------------------------+--------------+-----------+------------+-----------+-----------|
| v, v;[3] | *N* | *N* | y | y | y |

Notes:

  • [1] The result of the mask-mask == and != operation is a scalar.
  • [2] ++ (either kind) on bools is deprecated by the standard
  • [3] contrary to the other operators, the expected result for (sv1, sv2) is exactly sv2, no broadcasting applied.
  • [4] Checked with Vector<int>::Mask [SSE] and SimdArray<int, 4>::Mask, which behaved identical

Support levels:

  • y: operation generally works; some instances of the operation may not apply
  • *N*: operation generally does not work; some instances of the operation may not apply
  • n/a: operation does not apply (i.e. bitwise operations to floating-point operands, -- (and in the future possibly ++) to boolean operands, assignment operators to scalar left hand sides)

Each operation was tested with the full set of combinations of possible const/non-const lvalue/xvalue arguments. Each combination of constness and value category was applied to the scalar type and the operation tried in an SFINAE context; combinations that failed here were skipped for vector arguments too.

Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (Feb 21, 23:30, 2024)