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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20110803/9b3c712e/attachment.htm>
[Rcpp-devel] Passing an exposed function to another C++ function as a parameter
7 messages · Dirk Eddelbuettel, Romain Francois, Manuel Castejón Limas
Hi Manuel,
On 3 August 2011 at 08:22, Manuel Castej?n Limas wrote:
|
| 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
( I have a hard time with the formatting of your email. That table was
essentially unreadable. I even looked at Gmane's rendering at
http://article.gmane.org/gmane.comp.lang.r.rcpp/2301 which is also
broken. Can you work on your email setup? )
Profiling is a good idea. What we see here is that the ease of use comes at
some overhead for the wrapping and unwrapping it implies. Such is life --
Modules has some cost.
We do of course try to eliminate any obvious source of underperformance so
there is always scope for profiling and debugging. Help is always appreciated.
| 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 ?
Why don't you just access double tanh(double) itself? If Tanh_f0 a
mockup for the real function you want to use this way?
| 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?
No sorry, I don't have time to look through this now but XPtr per se is well
tested and reliable. It is meant to be used with external objects -- not
necessarily function pointers.
| Thank you for your patience in reading such long message!
Pleasure, and sorry I have no immediate fix for you.
Dirk
| 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
Gauss once played himself in a zero-sum game and won $50.
-- #11 at http://www.gaussfacts.com
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). 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. 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
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
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. 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
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
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