1+ // [[Rcpp::depends(RcppParallel)]]
2+ #include < RcppParallel.h>
3+ using namespace RcppParallel ;
4+
5+ #include < Rcpp.h>
6+ using namespace Rcpp ;
7+
8+ /* *
9+ * Let's use `Boost.SIMD` to compute the variance for a vector of numbers.
10+ * In contrast to the gallery article [implementing the sum](<TODO!!>),
11+ * we'll take advantage of some of the lower-level facilities provided
12+ * for interacting with packs of values.
13+ *
14+ * The imple
15+ */
16+
17+ class simd_ssq
18+ {
19+ public:
20+ explicit simd_ssq (double avg) : avg_(avg) {}
21+
22+ template <typename T>
23+ T operator ()(const T& t) {
24+ return boost::simd::sqr (t - avg_);
25+ }
26+
27+ private:
28+ double avg_;
29+ };
30+
31+ struct simd_plus
32+ {
33+ template <typename T>
34+ T operator ()(const T& lhs, const T& rhs) {
35+ return lhs + rhs;
36+ }
37+ };
38+
39+ // [[Rcpp::export]]
40+ double simdVar (NumericVector data) {
41+
42+ // Bring in the Boost.SIMD components we need
43+ using boost::simd::pack;
44+ using boost::simd::load;
45+ typedef pack<double > packed_type;
46+
47+ // Compute the mean of our dataset
48+ std::size_t n = data.size ();
49+ double total = boost::simd::accumulate (data.begin (), data.end (), 0.0 , simd_plus ());
50+ double avg = total / n;
51+
52+ // Create a functor that can be used to generate the sum of squares
53+ // for our above mean
54+ simd_ssq functor (avg);
55+
56+ // Generate a SIMD pack to hold intermediate
57+ // values of our computation (ensure it is zero-initialized)
58+ packed_type accumulated (0 );
59+
60+ // Get 'raw' iterators to the underlying data
61+ double * it = REAL (data);
62+ double * end = REAL (data) + n;
63+
64+ // Loop over chunks of our data, and compute the sum of squares
65+ while (it != end)
66+ {
67+ // Load the data
68+ packed_type loaded = load<packed_type>(it);
69+
70+ // Compute the sum of squares
71+ accumulated += functor (loaded);
72+
73+ // Advance our iterator to the next 'chunk' of data
74+ it += packed_type::static_size;
75+ }
76+
77+ // Finish off by summing the accumulated values and dividing
78+ // by (n - 1)
79+ return sum (accumulated) / (n - 1 );
80+
81+ }
82+
83+ /* ** R
84+ x <- rnorm(1E6)
85+ var(x)
86+ simdVar(x)
87+ microbenchmark::microbenchmark(var(x), simdVar(x))
88+ */
0 commit comments