[Rcpp-devel] Passing an exposed function to another C++ function as a parameter

Manuel Castejón Limas manuel.castejon at gmail.com
Wed Aug 3 22:06:09 CEST 2011


Thank you for your effort in summarizing the necessary steps using that
approach. In fact, as I mentioned in the first message, I did my search
before posting and I had already seen the sources of RcppDE --- sorry for
the misspell, I wrote RppDE in the first message. Using what I understood
from those sources I deviced my attempt which proved wrong due to my lack
of experience.

What I intend to do is slightly different. I'm trying to get access to the
pointer of the original function that I guess --- it's a supposition---,
is stored somewhere in the exposed function on the R side. I might be
wrong on that assumption and you might have implemented it in a different
manner.

The interest of doing that and used a exposed function is to lighten the
user of the package of the burden of having to deal with pointers. I
believe that the RCPP_MODULE construct is something I could ask a user to
deal with, but not much more given that many of them may not even have
experience on C++.

Having a look at :
 
> showClass("C++Function")
Class "C++Function" [package "Rcpp"]

Slots:
                   
Name:        .Data     pointer   docstring   signature
Class:    function externalptr   character   character

Extends: 
Class "function", from data part
Class "OptionalFunction", by class "function", distance 2
Class "PossibleMethod", by class "function", distance 2

We can see a pointer Slot. Is there any chance that this pointer would be
pointing at the original C++ function?


Thank you for your patience and support.
Manuel

 

El 03/08/11 19:22, "Dirk Eddelbuettel" <edd at debian.org> escribi¨®:

>
>On 3 August 2011 at 18:59, Manuel Castej¨®n Limas wrote:
>| Great! I'm eager to see the example. Thank you very much indeed!
>| 
>| I'm sorry about the formatting of the table, I'm used to write on a very
>| wide setting so it looked ok on my computer. I'll be more careful the
>next
>| time.
>| 
>| Though I did not mention it in the first message, the problem posed has
>| paramount importance for the new version of the AMORE package and may be
>| for many others to come.
>| 
>| The thing is that, in the case of AMORE ---a neural network
>simulator---,
>| the user of the package is provided the capability to write their own
>| neuron activation functions and training cost functions. In the stable
>| version on CRAN this is done by letting the user write those functions
>in
>| R language at the cost of a lower performance. Those users that are ok
>| with the functions provided in the package enjoy the benefits of
>compiled
>| code; those writing their own functions have to cope with a lower speed
>| unless they want to sink into the code of the package, but those are the
>| less I guess.
>| 
>| Now, thanks to Rcpp, a see a new possibility which is to let the user
>| write their own functions in C++ and use them along the provided ones in
>| the package following the scheme I was trying to get to work, and all
>that
>| without having to compromise performance.
>
>
>As Romain mentioned, I addressed that with my 'port' of DEoptim to Rcpp in
>the RcppDE package. It allows for user-defined objective functions that
>can
>be either supplied in R or C. Simple examples are in a demo file in the
>package, see demo(CompiledBenchmark) -- or more importantly, see its
>source
>and the RcppDE source.
>
>To take but one example, the 'Rastrigin' optimisation function is written
>(in
>DEoptim and other places) as
>
>    Rastrigin <- function(x) {
>        sum(x+2 - 10 * cos(2*pi*x)) + 20
>    }
>
>and we can supply a C++ variant as
>
>    double rastrigin(SEXP xs) {
>      Rcpp::NumericVector x(xs);
>      int n = x.size();
>      double sum = 20.0;
>      for (int i=0; i<n; i++) {
>        sum += x[i]+2 - 10*cos(2*M_PI*x[i]);
>      }
>    return(sum);
>
>from which we can build an XPtr object (where we actually switch over
>three
>different possibilities, here simplified):
>
>    typedef double (*funcPtr)(SEXP);
>    return(XPtr<funcPtr>(new funcPtr(&rastrigin)));
>
>and that XPtr is then passed down to the C++ code to be evaluated.
>
>Have a look at the demo, it may get you towards where you want to go.
>This
>is still pretty raw and drafty code in RcppDE; I stopped when it started
>to
>do what I wanted it to do.
>
>Cheers, Dirk
>
>
>| 
>| The point is that the Tanh_f0 function, shown as an example, or many
>| others will be written by the user if need be, while the rest of the
>code
>| involved in training the network will be provided by the package.
>| 
>| There's beauty indeed in being able to merge those two worlds.
>| 
>| Similarly, the same thing might be done with classes. A package could
>then
>| provide a framework and the users could extend the existing classes
>| customizing the behavior of the package with the ease of using inline.
>Now
>| I'm thinking about training algorithms in the case of AMORE.
>| 
>| But that's another story. For now, I'm dreaming on the example that
>Romain
>| is cooking.
>| 
>| PS: Did I mention you guys did a great job with Rcpp! I love it. It's a
>| revolutionary package in the R arena, IMHO.
>| 
>| 
>| 
>| El 03/08/11 15:29, "Dirk Eddelbuettel" <edd at debian.org> escribi¨®:
>| 
>| >
>| >On 3 August 2011 at 14:42, Romain Francois wrote:
>| >| Hi,
>| >| 
>| >| This looks very similar to a problem Dirk faced in rewriting the
>| >DEOptim 
>| >| package to use Rcpp (the RcppDE package is on the Rcpp svn repo).
>| >
>| >(and on CRAN)
>| > 
>| >| Essentially the problem is that the Rcpp::Function is a C++ object
>that
>| >| calls back to R, with additional protection, which eventually calls
>C++.
>| >| 
>| >| You should be able to bypass this entirely and access directly the
>| >| pointer to the C++ function from the R variable. This way, you stay
>in
>| >| the C++ world. This would allow you to branch your code depending on
>| >| whether you loop over a pure R function or a C++ function.
>| >| 
>| >| I'll cook an example.
>| >
>| >Cool, thanks. Maybe add it to the Rcpp-FAQ vignette too?
>| >
>| >Dirk
>| >
>| >| 
>| >| Romain
>| >| 
>| >| Le 03/08/11 08:22, Manuel Castej¨®n Limas a ¨¦crit :
>| >| >
>| >| >> Dear all,
>| >| >>
>| >| >> I'm rewriting the AMORE package using Rcpp --- in fact it's more
>like
>| >| >> I'm having a lot of fun while rewriting the AMORE package thanks
>to
>| >Rcpp.
>| >| >> Nevertheless, I'm facing this little problem that I hope it would
>be
>| >| >> pretty easy for you to solve.
>| >| >>
>| >| >> Let's consider the C++ function Tanh_f0
>| >| >>
>| >| >> double
>| >| >>
>| >| >> Tanh_f0(double inducedLocalField)
>| >| >>
>| >| >>   {
>| >| >>
>| >| >>     return tanh(inducedLocalField);
>| >| >>
>| >| >>   }
>| >| >>
>| >| >>
>| >| >> After compilation using inline, Tanh_f0 is exposed to R using
>Module
>| >| >> and accessible through actMod$Tanh_f0
>| >| >>
>| >| >>
>| >| >> actMod$Tanh_f0(0.1)
>| >| >>
>| >| >> # [1] 0.09966799
>| >| >>
>| >| >>
>| >| >> Now, I want to pass actMod$Tanh_f0 as a parameter of a function in
>| >| >> order to use the original C++ function Tanh_f0.
>| >| >>
>| >| >>
>| >| >>
>| >| >> testCode <- ' Rcpp::Function fx (myfun);
>| >| >>
>| >| >> double result = as<double>(fx(x));
>| >| >>
>| >| >> return wrap( result );
>| >| >>
>| >| >> '
>| >| >>
>| >| >> usingTanhf0 <- cfunction(sig=signature(myfun="function",
>| >x="numeric"),
>| >| >> body=testCode,Š)
>| >| >>
>| >| >>
>| >| >> And that indeed works, but when compared to using a simple tanh
>| >| >> function it shows quite a bad performance.
>| >| >>
>| >| >>
>| >| >>
>| >| >> testCode <- ' double value = as<double>(x);
>| >| >>
>| >| >> double result = tanh(value);
>| >| >>
>| >| >> return wrap( result );
>| >| >>
>| >| >> '
>| >| >>
>| >| >>
>| >| >> usingTanh <- cfunction(sig=signature(x="numeric"), body=testCode,
>Š )
>| >| >>
>| >| >> benchmark(usingTanhf0(myfun=actMod$Tanh_f0, x=0.1) , usingTanh(
>| >| >> x=0.1), columns=c("test", "replications", "elapsed", "relative"),
>| >| >> order="relative", replications=1000)
>| >| >>
>| >| >> #                                           test replications
>elapsed
>| >| >> relative
>| >| >>
>| >| >> # 2                           usingTanh(x = 0.1)         1000
>0.004
>| >| >>       1
>| >| >>
>| >| >> # 1 usingTanhf0(myfun = actMod$Tanh_f0, x = 0.1)         1000
>0.080
>| >| >>       20
>| >| >>
>| >| >>
>| >| >> Looks like having to go the R way to get access to Tanh_f0 has a
>high
>| >| >> cost. In order to be faster, it would be great if I could have
>access
>| >| >> to the original Tanh_f0 which I guess is pointed to by
>| >| >>  actMod$Tanh_f0, may be at the address 0x100153d30 ?
>| >| >>
>| >| >>
>| >| >> actMod$Tanh_f0
>| >| >>
>| >| >> # internal C++ function <0x100153d30>
>| >| >>
>| >| >> #     signature : double Tanh_f0(double)
>| >| >>
>| >| >>
>| >| >> After having had a look at RppDE sources, I guess the solution
>would
>| >| >> be to pass the function as an external pointer; something like :
>| >| >>
>| >| >> testCode <- '
>| >| >>
>| >| >> typedef double (*funPtr)(double) ;
>| >| >>
>| >| >> Rcpp::XPtr<  funPtr > fx (myfun);
>| >| >>
>| >| >> double result = (*fx)(0.1);
>| >| >>
>| >| >> return wrap( result );
>| >| >>
>| >| >> '
>| >| >>
>| >| >> testCodefun <- cfunction(sig=signature(myfun="C++Function"),
>| >| >> body=testCode,Š)
>| >| >>
>| >| >> result <- testCodefun(myfun=actMod$Tanh_f0)
>| >| >>
>| >| >>
>| >| >> But this does NOT work and crashes R.
>| >| >>
>| >| >> Any hints?
>| >| >>
>| >| >> Thank you for your patience in reading such long message!
>| >| >> Manuel
>| >| >>
>| >| >>
>| >| >>
>| >| >
>| >| >
>| >| > _______________________________________________
>| >| > Rcpp-devel mailing list
>| >| > Rcpp-devel at lists.r-forge.r-project.org
>| >| > 
>| >https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
>| >| 
>| >| 
>| >| -- 
>| >| Romain Francois
>| >| Professional R Enthusiast
>| >| +33(0) 6 28 91 30 30
>| >| http://romainfrancois.blog.free.fr
>| >| http://romain-francois.com
>| >| |- http://bit.ly/lJoWbH : Montpellier Com¨¦die Club - Juin 2011
>| >| |- http://bit.ly/kaSV6U : Stand up set at Up The Creek
>| >| `- http://bit.ly/hdKhCy : Rcpp article in JSS
>| >| 
>| >| 
>| >| _______________________________________________
>| >| Rcpp-devel mailing list
>| >| Rcpp-devel at lists.r-forge.r-project.org
>| >| 
>https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
>| >
>| >-- 
>| >Gauss once played himself in a zero-sum game and won $50.
>| >                      -- #11 at http://www.gaussfacts.com
>| 
>| 
>
>-- 
>Gauss once played himself in a zero-sum game and won $50.
>                      -- #11 at http://www.gaussfacts.com




More information about the Rcpp-devel mailing list