By Rcpp Gallery
Introduction
The Numerical Template Toolbox (NT2)
collection of header-only C++ libraries that make it
possible to explicitly request the use of SIMD instructions
when possible, while falling back to regular scalar
operations when not. NT2 itself is powered
by Boost, alongside two proposed
Boost libraries – Boost.Dispatch
, which provides a
mechanism for efficient tag-based dispatch for functions,
and Boost.SIMD
, which provides a framework for the
implementation of algorithms that take advantage of SIMD
instructions.RcppNT2
wraps
and exposes these libraries for use with R
.
If you haven’t already, read the
RcppNT2 introduction article
to get acquainted with the RcppNT2 package.
Computing the Sum
First, let’s review how we might use std::accumulate()
to sum a vector of numbers. We explicitly pass in thestd::plus()
functor, just to make it clear that
the std::accumulate()
algorithm expects a binary
functor when accumulating values.
#include using namespace Rcpp;
// [[Rcpp::export]]
double vectorSum(NumericVector x) {
return std::accumulate(x.begin(), x.end(), 0.0, std::plusdouble>());
}
Now, let’s rewrite this to take advantage of RcppNT2.
There are two main steps required to take advantage of
RcppNT2 at a high level:
-
Write a functor, with a templated call operator,
with the implementation written in a
‘Boost.SIMD
-aware’ way; -
Provide the functor as an argument to the
appropriate SIMD algorithm.
Let’s follow these steps in implementing our SIMD sum.
// [[Rcpp::depends(RcppNT2)]]
#include using namespace RcppNT2;
struct simd_plus {
template typename T>
T operator()(const T& lhs, const T& rhs) {
return lhs + rhs;
}
};
// [[Rcpp::export]]
double vectorSumSimd(NumericVector x) {
return simdReduce(x.begin(), x.end(), 0.0, simd_plus());
}
As you can see, it’s quite simple to take advantage ofBoost.SIMD
. For very simple operations such as this,
RcppNT2 provides a number of pre-defined functors,
which can be accessed in the RcppParallel::functor
namespace. The following is an equivalent way of defining
the above function:
// [[Rcpp::export]]
double vectorSumSimdV2(NumericVector x) {
return simdReduce(x.begin(), x.end(), 0.0, functor::plus());
}
Behind the scenes of simdReduce()
, Boost.SIMD
will
apply your templated functor to ‘packs’ of values when
appropriate, …read more
Source:: r-bloggers.com