Multivectors and multiexpressions¶
The vex::multivector<T,N>
class allows to store several equally
sized device vectors and perform computations on each component in sync. Each
operation is delegated to the underlying vectors, but usually results in the
launch of a single fused kernel. Expressions may include values of
std::array<T,N>
where N
is equal to the number of multivector
components, or appropriately sized tuples. Each component gets the
corresponding element of either the array or the tuple when the expression is
applied. Similarly, vex::multivector::operator[]()
or reduction of a
multivector returns an instance of std::array<T,N>
.
vex::multivector::operator()()
allows to access individual components
of a multivector.
Some examples:
VEX_FUNCTION(bool, between, (double, a)(double, b)(double, c),
return a <= b && b <= c;
);
vex::Reductor<double, vex::SUM> sum(ctx);
vex::SpMat<double> A(ctx, ... );
std::array<double, 2> v = {6.0, 7.0};
vex::multivector<double, 2> X(ctx, N), Y(ctx, N);
// ...
X = sin(v * Y + 1); // X(k) = sin(v[k] * Y(k) + 1);
v = sum( between(0, X, Y) ); // v[k] = sum( between( 0, X(k), Y(k) ) );
X = A * Y; // X(k) = A * Y(k);
Some operations can not be expressed with simple multivector arithmetic. For example, an operation of two dimensional rotation mixes components in the right hand side expressions:
This may in principle be implemented as:
double alpha;
vex::multivector<double, 2> X(ctx, N), Y(ctx, N);
Y(0) = X(0) * cos(alpha) - X(1) * sin(alpha);
Y(1) = X(0) * sin(alpha) + X(1) * cos(alpha);
But this would result in two kernel launches instead of single fused launch. VexCL allows one to assign a tuple of expressions to a multivector, which will lead to the launch of a single fused kernel:
Y = std::make_tuple(
X(0) * cos(alpha) - X(1) * sin(alpha),
X(0) * sin(alpha) + X(1) * cos(alpha) );
vex::tie()
function even allows to get rid of multivectors completely
and fuse several vector expressions into a single kernel. We can rewrite the
above examples with just vex::vector<double>
instances:
vex::vector<double> x0(ctx, N), x1(ctx,N), y0(ctx, N), y1(ctx, N);
vex::tie(y0, y1) = std::make_tuple(
x0 * cos(alpha) - x1 * sin(alpha),
x0 * sin(alpha) + x1 * cos(alpha) );
-
template<typename T, size_t N>
class vex::multivector : public vex::multivector_expression<Expr>¶ Container for several equally sized instances of vex::vector<T>.
Public Functions
-
inline multivector(const std::vector<backend::command_queue> &queue, const std::vector<T> &host, backend::mem_flags flags = backend::MEM_READ_WRITE)¶
Constructor.
The host vector data is divided equally between the created multivector components. Each component gets continuous chunk of the source vector.
-
inline multivector(const std::vector<backend::command_queue> &queue, size_t size, const T *host = 0, backend::mem_flags flags = backend::MEM_READ_WRITE)¶
Constructor.
If host pointer is not NULL, it is copied to the underlying vector components of the multivector. Each component gets continuous chunk of the source vector.
-
inline multivector(size_t size)¶
Constructor.
Uses the most recently created VexCL context.
-
inline multivector(const multivector &mv)¶
Copy constructor.
-
inline multivector(multivector &&mv) noexcept¶
Move constructor.
-
inline void resize(const std::vector<backend::command_queue> &queue, size_t size)¶
Resizes the multivector.
This is equivalent to reconstructing the vector with the given parameters. Any data contained in the resized vector will be lost as a result.
-
inline void resize(size_t size)¶
Resizes the multivector.
Uses the most recently created VexCL context. This is equivalent to reconstructing the vector with the given parameters. Any data contained in the resized vector will be lost as a result.
-
inline void clear()¶
Fills the multivector with zeros.
-
inline size_t size() const¶
Returns size of the multivector (equals size of individual components).
-
inline const_iterator begin() const¶
Returns const iterator to the first element of the multivector.
-
inline iterator begin()¶
Returns const iterator to the first element of the multivector.
-
inline const_iterator end() const¶
Returns const iterator referring to the past-the-end element in the multivector.
-
inline iterator end()¶
Returns iterator referring to the past-the-end element in the multivector.
-
inline const_element operator[](size_t i) const¶
Returns i-th elements of all components packed in a std::array<T,N>.
-
inline element operator[](size_t i)¶
Assigns values from std::array<T,N> to i-th elements of all components.
-
inline const std::vector<backend::command_queue> &queue_list() const¶
Returns reference to the multivector’s queue list.
-
inline const multivector &operator=(const multivector &mv)¶
Assignment operator.
-
template<class Expr>
inline auto operator=(const Expr &expr) -> typename std::enable_if<boost::proto::matches<typename boost::proto::result_of::as_expr<Expr>::type, multivector_expr_grammar>::value || is_tuple<Expr>::value, const multivector&>::type¶ Assignment operator
-
template<class Expr>
inline auto operator+=(const Expr &expr) -> typename std::enable_if<boost::proto::matches<typename boost::proto::result_of::as_expr<Expr>::type, multivector_expr_grammar>::value || is_tuple<Expr>::value, const multivector&>::type¶ Assignment operator
-
template<class Expr>
inline auto operator-=(const Expr &expr) -> typename std::enable_if<boost::proto::matches<typename boost::proto::result_of::as_expr<Expr>::type, multivector_expr_grammar>::value || is_tuple<Expr>::value, const multivector&>::type¶ Assignment operator
-
template<class Expr>
inline auto operator*=(const Expr &expr) -> typename std::enable_if<boost::proto::matches<typename boost::proto::result_of::as_expr<Expr>::type, multivector_expr_grammar>::value || is_tuple<Expr>::value, const multivector&>::type¶ Assignment operator
-
template<class Expr>
inline auto operator/=(const Expr &expr) -> typename std::enable_if<boost::proto::matches<typename boost::proto::result_of::as_expr<Expr>::type, multivector_expr_grammar>::value || is_tuple<Expr>::value, const multivector&>::type¶ Assignment operator
-
template<class Expr>
inline auto operator%=(const Expr &expr) -> typename std::enable_if<boost::proto::matches<typename boost::proto::result_of::as_expr<Expr>::type, multivector_expr_grammar>::value || is_tuple<Expr>::value, const multivector&>::type¶ Assignment operator
-
template<class Expr>
inline auto operator&=(const Expr &expr) -> typename std::enable_if<boost::proto::matches<typename boost::proto::result_of::as_expr<Expr>::type, multivector_expr_grammar>::value || is_tuple<Expr>::value, const multivector&>::type¶ Assignment operator
-
template<class Expr>
inline auto operator|=(const Expr &expr) -> typename std::enable_if<boost::proto::matches<typename boost::proto::result_of::as_expr<Expr>::type, multivector_expr_grammar>::value || is_tuple<Expr>::value, const multivector&>::type¶ Assignment operator
-
template<class Expr>
inline auto operator^=(const Expr &expr) -> typename std::enable_if<boost::proto::matches<typename boost::proto::result_of::as_expr<Expr>::type, multivector_expr_grammar>::value || is_tuple<Expr>::value, const multivector&>::type¶ Assignment operator
-
template<class Expr>
inline auto operator<<=(const Expr &expr) -> typename std::enable_if<boost::proto::matches<typename boost::proto::result_of::as_expr<Expr>::type, multivector_expr_grammar>::value || is_tuple<Expr>::value, const multivector&>::type¶ Assignment operator
-
template<class Expr>
inline auto operator>>=(const Expr &expr) -> typename std::enable_if<boost::proto::matches<typename boost::proto::result_of::as_expr<Expr>::type, multivector_expr_grammar>::value || is_tuple<Expr>::value, const multivector&>::type¶ Assignment operator
-
class const_element¶
-
class element¶
-
template<class V, class E>
class iterator_type : public boost::iterator_facade<iterator_type<V, E>, sub_value_type, std::random_access_iterator_tag, E>¶
-
inline multivector(const std::vector<backend::command_queue> &queue, const std::vector<T> &host, backend::mem_flags flags = backend::MEM_READ_WRITE)¶
-
template<class ...Expr>
auto vex::tie(const Expr&... expr) -> expression_tuple<std::tuple<const Expr&...>>¶ Ties several vector expressions into a writeable tuple.
The following example results in a single kernel:
vex::vector<double> x(ctx, 1024); vex::vector<double> y(ctx, 1024); vex::tie(x,y) = std::make_tuple( x + y, y - x );
This is functionally equivalent to the following code, but does not use temporary vectors and is more efficient:
tmp_x = x + y; tmp_y = y - x; x = tmp_x; y = tmp_y;