vspline 1.1.0
Generic C++11 Code for Uniform B-Splines
Classes | Namespaces | Macros | Typedefs | Functions
vector.h File Reference

code for horizontal vectorization in vspline More...

#include "common.h"
#include "simd_type.h"
#include "vc_simd_type.h"

Go to the source code of this file.

Classes

struct  vspline::simd_traits< T >
 traits class simd_traits provides three traits: More...
 
struct  vspline::vector_traits< T, _vsize, Enable >
 with the definition of 'simd_traits', we can proceed to implement 'vector_traits': struct vector_traits is a traits class fixing the types used for vectorized code in vspline. These types go beyond mere vectors of fundamentals: most of the time, the data vspline has to process are not fundamentals, but what I call 'xel' data: pixels, voxels, stereo sound samples, etc. - so, small aggregates of a fundamental type. vector_traits defines how fundamentals and 'xel' data are to be vectorized. with the types defined by vector_traits, a system of type names is introduced which uses a set of patterns: More...
 
struct  vspline::vector_traits< T, _vsize, typename std::enable_if< vspline::is_element_expandable< T > ::value > ::type >
 specialization of vector_traits for 'element-expandable' types. These types are recognized by vigra's ExpandElementResult mechanism, resulting in the formation of a 'vectorized' version of the type. These data are what I call 'xel' data. As explained above, vectorization is horizontal, so if T is, say, a pixel of three floats, the type generated here will be a TinyVector of three vectors of vsize floats. More...
 

Namespaces

namespace  vspline
 

Macros

#define VC_SIMD(T)
 

Typedefs

template<typename T , size_t N>
using vspline::simdized_type = typename vector_traits< T, N > ::type
 this alias is used as a shorthand to pick the vectorized type for a given type T and a size N from 'vector_traits': More...
 

Functions

template<typename T , typename U >
void vspline::assign (T &t, const U &u)
 
template<typename T , typename U , int N>
void vspline::assign (vigra::TinyVector< T, N > &t, const vigra::TinyVector< U, N > &u)
 
template<typename VT1 , typename PT , typename VT2 >
void vspline::assign_if (VT1 &target, const PT &predicate, const VT2 &source)
 
template<typename T >
void vspline::assign_if (T &target, const bool &predicate, const T &source)
 

Detailed Description

code for horizontal vectorization in vspline

vspline currently has three ways of approaching vectorization:

It's important to understand that using SIMD is not simply mapping, say, pixels of three floats to a vector of three floats - that would be 'vertical' vectorization, which is represented by vspline's scalar code. Instead, vspline is coded to use horizontal vectorization, which produces vector data fitting the size of the vector unit's registers, where each element held by the vector has exactly the same meaning as every other: rather than vectors holding, like, the colour channels of a pixel, we have a 'red', a 'green' and a 'blue' vector holding, say, eight floats each. Horizontal vectorization is best explicitly coded, and if it is coded explicitly, the code structure itself suggests vectorization to the compiler. Using code like Vc gives more structure to this process and adds capabilities beyond the scope of autovectorization, but having the horizontal vectorization manifest in the code's structure already goes a long way, and if the 'structurally' vectorized code autovectorizes well, that may well be 'good enough' as it is. In my experience, it is often significantly faster than scalar code - provided the processor has vector units.

So it turns out that successful vectorization is, to a large degree, a conceptual change making the intended vectorization explicit by choosing appropriate data types. I am indebted to Matthis Kretz, the author of the Vc library, who has opened my eyes to this fact with his thesis: 'Extending C++ for explicit data-parallel programming via SIMD vector types'.

With vspline::simd_type 'in the back hand' vspline code can rely on the presence of a vectorized type for every fundamental, and, by extension, vectorized 'xel' data - i.e. vectorized pixels, voxels etc. which are implemented as vigra::TinyVectors of vectorized fundamentals. This allows vspline to be coded so that it relies on vectorization, but not necessarily on Vc: Vc is an option to provide extra-fast, tailormade vector code for some operations, but when it can't be used, vspline's own vector code will be used instead, providing the same interface. This makes maintainance much easier compared to a scenario where, without Vc, the code would have to fall back to a scalar version - as indeed it did in early vspline versions, giving me plenty of headaches.

Note that this header is included by vspline/common.h, so this code is available throughout vspline.

Definition in file vector.h.

Macro Definition Documentation

◆ VC_SIMD

#define VC_SIMD (   T)
Value:
template<> struct simd_traits<T> \
{ \
static const size_t hsize = Vc::Vector < T > :: size() ; \
template < size_t sz > using type = \
typename std::conditional \
< sz == 1 , \
T , \
vc_simd_type < T , sz > \
> :: type ; \
enum { default_size = sizeof ( T ) > VSPLINE_VECTOR_NBYTES \
? 1 \
: VSPLINE_VECTOR_NBYTES / sizeof ( T ) } ; \
} ;
#define VSPLINE_VECTOR_NBYTES

Definition at line 248 of file vector.h.