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" <e...@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@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@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 _______________________________________________ Rcpp-devel mailing list Rcpp-devel@lists.r-forge.r-project.org https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel