[Rcpp-devel] Repeatedly evaluating external C++ function in the same environment

Antonio Coppola acoppola at college.harvard.edu
Tue Aug 5 18:08:55 CEST 2014


Yes, definitely. Thank you for your reply, Dirk! I will keep looking into
this and send an update if I figure out something.


On Tue, Aug 5, 2014 at 11:27 AM, Dirk Eddelbuettel <edd at debian.org> wrote:

>
> Hi Antonio,
>
> On 5 August 2014 at 11:03, Antonio Coppola wrote:
> | Hello RCPP,
> |
> | There is a puzzle that I have been wrestling with for a while now. This
> is in
> | the context of a package for numerical optimization. The underlying
> | implementation is, of course, in C++. I’d like to let the user pass in
> both R
> | functions and external pointers to C++ for function evaluation, much
> like in
> | the RcppDE package. I also want the user to be able to pass in an
> environment
> | in which to evaluate the function. So far so good. No issue doing that
> with the
> | R functions, and for the C++ pointers I define a class after the RcppDE
> model:
> |
> | class EvalCompiled : public EvalBase {
> |         public:
> |             EvalCompiled(Rcpp::XPtr<funcPtr> xptr, SEXP __env) {
> |                 funptr = *(xptr);
> |                 env = __env;
> |             };
> |             EvalCompiled(SEXP xps, SEXP __env) {
> |                 Rcpp::XPtr<funcPtr> xptr(xps);
> |                 funptr = *(xptr);
> |                 env = __env;
> |             };
> |              Rcpp::NumericVector eval(SEXP par) {
> |                 neval++;
> |                 return funptr(par, env);
> |             }
> |         private:
> |             funcPtr funptr;
> |
> |             SEXP env;
> |         };
> |
> | The user has to create the external pointer using inline in R. The
> following is
> | an example using a logit regression setup with ridge penalty. The extra
> | environment is required to pass in the data:
> |
> | lhoodL2.inc <- 'Rcpp::NumericVector lhood(SEXP xs, SEXP env){
> |   arma::vec par = Rcpp::as<arma::vec>(xs);
> |   Rcpp::Environment e = Rcpp::as<Rcpp::Environment>(env);
> |   arma::mat X = Rcpp::as<arma::mat>(e["X"]);
> |   arma::vec y = Rcpp::as<arma::vec>(e["y"]);
> |   double prec = Rcpp::as<double>(e["prec"]);
> |   arma::mat Xbeta = X * par;
> |   double sum1 = sum(y % Xbeta - log(1 + exp(Xbeta)));
> |   arma::mat sum2 = sum(pow(par, 2 * prec));
> |   arma::vec out = -(sum1 - 0.5 * sum2);
> |   Rcpp::NumericVector ret = Rcpp::as<Rcpp::NumericVector>(wrap(out));
> |   return ret;
> | }
> | '
> |
> | lhoodL2.body <- '
> |      typedef Rcpp::NumericVector (*funcPtr)(SEXP, SEXP);
> |      return(XPtr<funcPtr>(new funcPtr(&lhood)));
> |      '
> |
> | lhoodL2.CPP <- cxxfunction(signature(), body=lhoodL2.body,
> |                           inc=lhoodL2.inc, plugin="RcppArmadillo")
> |
> | # Passing in some data
> | env <- new.env()
> | env[["X"]] <- X
> | env[["y"]] <- y
> | env[["prec"]] <- prec
> |
> | output <- myNumericalOptimizationFun(lhoodL2.CPP(), c(-1.2,1),
> environment=env)
> |
> | The external pointer is passed into the numerical optimization routine,
> and
> | then the function is evaluated repeatedly until the optimization
> algorithm
> | reaches convergence. Now this works, but there is a big inefficiency
> here,
> | which is presumably slowing down things a lot. Namely, the data in the
> | environment is copied in memory at each iteration of the function, even
> though
> | this is not actually necessary. One would only need to copy the objects
> in
> | memory the first time the function is evaluated, and then reference them
> with a
> | pointer for the next iterations. Can you envision any way of doing this
> within
> | the context of the RCPP framework?
>
> Hm. Excellent question, and I quite like the XPtr use -- and I mentioned
> this
> very trick for this very use in talks / workshops at U Chicago and U
> Kansas.
>
> The environment should not get copied if it isn't altered.  You could try
> the  Rcpp::Environment class.
>
> Or you could try constructing an outer object holding the data, ensuring
> there is only one and then supplying an accessor object.  I know I am being
> brief here but does that makes sense to you?
>
> Dirk
>
> --
> http://dirk.eddelbuettel.com | @eddelbuettel | edd at debian.org
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20140805/ba815bf6/attachment.html>


More information about the Rcpp-devel mailing list