@@ -5,84 +5,50 @@ using namespace RcppParallel;
55#include < Rcpp.h>
66using namespace Rcpp ;
77
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
8+ class VarianceTransformer : public SimdTransformer <double >
189{
1910public:
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_ );
11+ packed_type initialize ( const value_type* begin, const value_type* end)
12+ {
13+ n_ = end - begin;
14+ mean_ = boost::simd::accumulate (begin, end, 0.0 , plus ()) / n_;
15+ return packed_type ( 0 );
2516 }
2617
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;
18+ void update (const packed_type& data, packed_type* pBuffer)
19+ {
20+ *pBuffer += boost::simd::sqr (data - mean_);
3621 }
37- };
38-
39- // [[Rcpp::export]]
40- double simdVar (NumericVector data) {
4122
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)
23+ value_type reduce (const packed_type& data)
6624 {
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;
25+ return sum (data) / (n_ - 1 );
7526 }
7627
77- // Finish off by summing the accumulated values and dividing
78- // by (n - 1)
79- return sum (accumulated) / (n - 1 );
28+ private:
8029
30+ struct plus
31+ {
32+ template <typename T>
33+ T operator ()(const T& lhs, const T& rhs)
34+ {
35+ return lhs + rhs;
36+ }
37+ };
38+
39+ double mean_;
40+ std::size_t n_;
41+ };
42+
43+ // [[Rcpp::export]]
44+ double simdVar (NumericVector data) {
45+ return simdTransformAndReduce (data.begin (), data.end (), VarianceTransformer ());
8146}
8247
8348/* ** R
8449x <- rnorm(1E6)
8550var(x)
8651simdVar(x)
87- microbenchmark::microbenchmark(var(x), simdVar(x))
52+ result <- microbenchmark::microbenchmark(var(x), simdVar(x))
53+ print(result, unit = "relative")
8854*/
0 commit comments