[Rcpp-devel] Minimal Working Example for RcppParallel gives nonsensical results

steven pav shabbychef at gmail.com
Fri Mar 25 19:26:33 CET 2016


(Based on this Q: http://stackoverflow.com/q/36206524/164611 , and
available from this gist:
https://gist.github.com/shabbychef/9c2ed6b2ee92f104a8b1 )

I am trying to write some code using the parallelReduce framework from
RcppParallel. Somehow I must be violating thread safety. I reduced my real
code down to a simple MWE that does not work. I'll include it below. This
very silly example just computes the length of an input vector. I thought
it was working correctly, but noticed that if I ran it many times quickly
(via replicate in R), I would get different answers. Per Dirk's advice, I
tried to remove any hint of Rcpp functions to maintain thread safety, but I
am not sure what is left. Any help appreciated.

yunoparallel.cpp:

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::depends(RcppParallel)]]
#include <RcppParallel.h>
using namespace RcppParallel;

// accumulate # of elements seen on the input iterator.
void accum_nel_int(RVector<double>::const_iterator vecit,
                   RVector<double>::const_iterator end,
                   RVector<int>::iterator xret) {
    for (;vecit != end;++vecit) { *xret += 1; }
}
void join_em_int(RVector<int> lhs, const RVector<int> rhs) {
    lhs[0] += rhs[0];
}

struct NEL_int : public Worker
{
   // source vector
   const RVector<double> input;
   // accumulated value
   RVector<int> output;

   // constructors
   NEL_int(const NumericVector input, IntegerVector output) : input(input),
output(output) {}
   NEL_int(const NEL_int& othr, Split) : input(othr.input),
output(othr.output) {}

   // accumulate just the element of the range I've been asked to
   void operator()(std::size_t begin, std::size_t end) {
       accum_nel_int(input.begin() + begin, input.begin() + end,
output.begin());
   }

   // join my value with that of another NEL_int
   void join(const NEL_int& rhs) {
       join_em_int(output,rhs.output);
   }
};

// dumb example counting # of elements on input:
// [[Rcpp::export]]
IntegerVector dumbCount_int(NumericVector x) {
   // allocate the output
   IntegerVector output(1);
   // declare the instance
   NEL_int wrkr(x,output);
   // call parallel_reduce to start the work
   parallelReduce(0, x.length(), wrkr, 5000);
   // return the computed number of non-na elements
   return output;
}

//for vim modeline: (do not edit)
//
vim:ts=4:sw=4:tw=79:fdm=marker:fmr=FOLDUP,UNFOLD:cms=//%s:syn=cpp:ft=cpp:ai:si:et:cin:nu:fo=croql:cino=p0t0c5(0:

In R:

library(Rcpp)
source('yunoparallel.cpp')
x <- rnorm(1e5)
dumbCount_int(x)
dumbCount_int(x)
# fine, right? no.
replicate(10,dumbCount_int(x))
sd(replicate(100,dumbCount_int(x)))

sessionInfo:

> sessionInfo()
R version 3.2.4 Revised (2016-03-16 r70336)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 14.04.4 LTS

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C
LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8
LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                  LC_ADDRESS=C
          LC_TELEPHONE=C             LC_MEASUREMENT=en_US.UTF-8
LC_IDENTIFICATION=C

attached base packages:
[1] graphics  grDevices datasets  stats     utils     methods   base

other attached packages:
[1] Rcpp_0.12.3     colorout_1.1-2  fortunes_1.5-2  Quandl_2.7.0
 xts_0.9-7       zoo_1.7-12      devtools_1.10.0 drat_0.1.0

loaded via a namespace (and not attached):
[1] httr_1.1.0          R6_2.1.2            tools_3.2.4
memoise_1.0.0       grid_3.2.4          jsonlite_0.9.19     digest_0.6.9
     RcppParallel_4.3.15
[9] lattice_0.20-33


-- 

--sep
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20160325/80a55af3/attachment.html>


More information about the Rcpp-devel mailing list