Hey there,
Looking at some old R code that I have I found this C++ function that
allows evaluating R-written functions within C++ using Rcpp. While this is
no news, the neat thing of it is that it seems to be faster than
Rcpp::Function. Using microbenchmark I compared using Rcpp::function vs my
implementation vs calling the function from R itself and this is what I got
Unit: relative
expr min lq mean median uq max neval
cppFuncall(x, fun) 1.3 1.3 1.39 1.3 1.4 83 10000
RcppFuncall(x, fun) 7.2 7.1 7.13 6.9 6.8 89 10000
fun(x) 1.0 1.0 1.00 1.0 1.0 1 10000
So, on average, while Rcpp::Function took ~7 times the R call took, my
implementation took ~1.3 times. To be sure I was not breaking anything I
ran the example using valgrind and there is no memory leak. The source code
for the test follows:
-------- example_calling_r_functions.cpp ----
#include <Rinternals.h>
#include <Rcpp.h>
// [[Rcpp::export]]
SEXP cppFuncall(SEXP par, SEXP fn)
{
SEXP R_fcall, ans;
if(!isFunction(fn)) error("'fn' must be a function");
R_fcall = PROTECT(lang2(fn, R_NilValue));
SETCADR(R_fcall, par);
ans=eval(R_fcall, R_GlobalEnv);
UNPROTECT(1);
return ans;
}
using namespace Rcpp;
// [[Rcpp::export]]
SEXP RcppFuncall(NumericVector par, Function fn)
{
return fn(par);
}
/*** R
# R function to be called
fun <- function(x) {
-cos(x[1])*cos(x[2])*exp(-((x[1] - pi)^2 + (x[2] - pi)^2))
}
# Input data
set.seed(3331)
x <- runif(1e3)
# Benchmarking
library(microbenchmark)
microbenchmark(
cppFuncall(x, fun), RcppFuncall(x,fun), fun(x), times=1e4,
unit="relative", control = list(warmup=100)
)
*/
-------- example_calling_r_functions.cpp ----
I've asked around about how to make things faster for function calls in
Rcpp but, from what I've been told it is difficult since the implementation
of Rcpp::Function actually has to go back to R to work (or something like
that :P). Now, this implementation, -cppFuncall-, has no problem when it
comes to passing wrong arguments, e.g. if you pass a character vector to it
R will complain but there won't be any system crash. One big difference is
that here I'm relying on passing all the function's arguments in a single
object while Rcpp::Function does not. Either way, if this is OK this could
be a nice extra feature for Rcpp, I'm thinking of optimization routines (or
other kinds of algorithms) that rely on calling R functions multiple times.
The thing is that I'm still learning C++ and I'm not Rinternals expert at
all! So I would love to get some feedback from you guys. Does this
function, -cppFuncall-, looks OK? in other words, am I doing/getting
something wrong here?
Thanks,
George G. Vega Yon
+1 (626) 381 8171
http://www.its.caltech.edu/~gvegayon/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20160803/d8814ddc/attachment.html>
[Rcpp-devel] Alternative way of calling R functions within C++
7 messages · Dirk Eddelbuettel, Kevin Ushey, George Vega Yon
The problem with your implementation is what happens if R throws an error. The R longjmp will cause any C++ objects on the stack to leak, their destructors not to run, and you'll essentially be in a bad place if you evaluate any R code that might return an error. (For example, suppose you had a file handle open, and then evaluated your R function using 'eval', but an R error was produced. That file handle would 'leak' and you wouldn't be able to recover it) You can instead use the `Rf_tryEval` or `Rf_tryEvalSilent` routines, but those don't respect active handlers (e.g. warning, message handlers) and so aren't sufficient for general use. Rcpp basically handles this by enclosing any expression to be evaluated in an R 'tryCatch' call, with error + interrupt handlers attached. This is, of course, slower since a lot more R code is being evaluated, but right now it's the only way to safely execute an R function in a C++ context while respecting all other active handlers. In short, the Rcpp::Function implementation is designed to be as safe + correct as possible, with the downside being that it's slower. However, we generally advise that you shouldn't call back to R too frequently from a C++ context, so that overhead should in most cases be not too bad. Best, Kevin
On Wed, Aug 3, 2016 at 10:50 AM, George Vega Yon <g.vegayon at gmail.com> wrote:
Hey there,
Looking at some old R code that I have I found this C++ function that allows
evaluating R-written functions within C++ using Rcpp. While this is no news,
the neat thing of it is that it seems to be faster than Rcpp::Function.
Using microbenchmark I compared using Rcpp::function vs my implementation vs
calling the function from R itself and this is what I got
Unit: relative
expr min lq mean median uq max neval
cppFuncall(x, fun) 1.3 1.3 1.39 1.3 1.4 83 10000
RcppFuncall(x, fun) 7.2 7.1 7.13 6.9 6.8 89 10000
fun(x) 1.0 1.0 1.00 1.0 1.0 1 10000
So, on average, while Rcpp::Function took ~7 times the R call took, my
implementation took ~1.3 times. To be sure I was not breaking anything I ran
the example using valgrind and there is no memory leak. The source code for
the test follows:
-------- example_calling_r_functions.cpp ----
#include <Rinternals.h>
#include <Rcpp.h>
// [[Rcpp::export]]
SEXP cppFuncall(SEXP par, SEXP fn)
{
SEXP R_fcall, ans;
if(!isFunction(fn)) error("'fn' must be a function");
R_fcall = PROTECT(lang2(fn, R_NilValue));
SETCADR(R_fcall, par);
ans=eval(R_fcall, R_GlobalEnv);
UNPROTECT(1);
return ans;
}
using namespace Rcpp;
// [[Rcpp::export]]
SEXP RcppFuncall(NumericVector par, Function fn)
{
return fn(par);
}
/*** R
# R function to be called
fun <- function(x) {
-cos(x[1])*cos(x[2])*exp(-((x[1] - pi)^2 + (x[2] - pi)^2))
}
# Input data
set.seed(3331)
x <- runif(1e3)
# Benchmarking
library(microbenchmark)
microbenchmark(
cppFuncall(x, fun), RcppFuncall(x,fun), fun(x), times=1e4,
unit="relative", control = list(warmup=100)
)
*/
-------- example_calling_r_functions.cpp ----
I've asked around about how to make things faster for function calls in Rcpp
but, from what I've been told it is difficult since the implementation of
Rcpp::Function actually has to go back to R to work (or something like that
:P). Now, this implementation, -cppFuncall-, has no problem when it comes to
passing wrong arguments, e.g. if you pass a character vector to it R will
complain but there won't be any system crash. One big difference is that
here I'm relying on passing all the function's arguments in a single object
while Rcpp::Function does not. Either way, if this is OK this could be a
nice extra feature for Rcpp, I'm thinking of optimization routines (or other
kinds of algorithms) that rely on calling R functions multiple times.
The thing is that I'm still learning C++ and I'm not Rinternals expert at
all! So I would love to get some feedback from you guys. Does this function,
-cppFuncall-, looks OK? in other words, am I doing/getting something wrong
here?
Thanks,
George G. Vega Yon
+1 (626) 381 8171
http://www.its.caltech.edu/~gvegayon/
_______________________________________________ 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
Also note that you definitely don't want to call `Rf_error` from a C++ context in general, as it will bypass any active C++ try-catch blocks, bypass destructors, and so on. You should call `Rcpp::stop` explicitly and use Rcpp attributes to ensure the try-catch block is automagically set up for you.
On Wed, Aug 3, 2016 at 11:28 AM, Kevin Ushey <kevinushey at gmail.com> wrote:
The problem with your implementation is what happens if R throws an error. The R longjmp will cause any C++ objects on the stack to leak, their destructors not to run, and you'll essentially be in a bad place if you evaluate any R code that might return an error. (For example, suppose you had a file handle open, and then evaluated your R function using 'eval', but an R error was produced. That file handle would 'leak' and you wouldn't be able to recover it) You can instead use the `Rf_tryEval` or `Rf_tryEvalSilent` routines, but those don't respect active handlers (e.g. warning, message handlers) and so aren't sufficient for general use. Rcpp basically handles this by enclosing any expression to be evaluated in an R 'tryCatch' call, with error + interrupt handlers attached. This is, of course, slower since a lot more R code is being evaluated, but right now it's the only way to safely execute an R function in a C++ context while respecting all other active handlers. In short, the Rcpp::Function implementation is designed to be as safe + correct as possible, with the downside being that it's slower. However, we generally advise that you shouldn't call back to R too frequently from a C++ context, so that overhead should in most cases be not too bad. Best, Kevin On Wed, Aug 3, 2016 at 10:50 AM, George Vega Yon <g.vegayon at gmail.com> wrote:
Hey there,
Looking at some old R code that I have I found this C++ function that allows
evaluating R-written functions within C++ using Rcpp. While this is no news,
the neat thing of it is that it seems to be faster than Rcpp::Function.
Using microbenchmark I compared using Rcpp::function vs my implementation vs
calling the function from R itself and this is what I got
Unit: relative
expr min lq mean median uq max neval
cppFuncall(x, fun) 1.3 1.3 1.39 1.3 1.4 83 10000
RcppFuncall(x, fun) 7.2 7.1 7.13 6.9 6.8 89 10000
fun(x) 1.0 1.0 1.00 1.0 1.0 1 10000
So, on average, while Rcpp::Function took ~7 times the R call took, my
implementation took ~1.3 times. To be sure I was not breaking anything I ran
the example using valgrind and there is no memory leak. The source code for
the test follows:
-------- example_calling_r_functions.cpp ----
#include <Rinternals.h>
#include <Rcpp.h>
// [[Rcpp::export]]
SEXP cppFuncall(SEXP par, SEXP fn)
{
SEXP R_fcall, ans;
if(!isFunction(fn)) error("'fn' must be a function");
R_fcall = PROTECT(lang2(fn, R_NilValue));
SETCADR(R_fcall, par);
ans=eval(R_fcall, R_GlobalEnv);
UNPROTECT(1);
return ans;
}
using namespace Rcpp;
// [[Rcpp::export]]
SEXP RcppFuncall(NumericVector par, Function fn)
{
return fn(par);
}
/*** R
# R function to be called
fun <- function(x) {
-cos(x[1])*cos(x[2])*exp(-((x[1] - pi)^2 + (x[2] - pi)^2))
}
# Input data
set.seed(3331)
x <- runif(1e3)
# Benchmarking
library(microbenchmark)
microbenchmark(
cppFuncall(x, fun), RcppFuncall(x,fun), fun(x), times=1e4,
unit="relative", control = list(warmup=100)
)
*/
-------- example_calling_r_functions.cpp ----
I've asked around about how to make things faster for function calls in Rcpp
but, from what I've been told it is difficult since the implementation of
Rcpp::Function actually has to go back to R to work (or something like that
:P). Now, this implementation, -cppFuncall-, has no problem when it comes to
passing wrong arguments, e.g. if you pass a character vector to it R will
complain but there won't be any system crash. One big difference is that
here I'm relying on passing all the function's arguments in a single object
while Rcpp::Function does not. Either way, if this is OK this could be a
nice extra feature for Rcpp, I'm thinking of optimization routines (or other
kinds of algorithms) that rely on calling R functions multiple times.
The thing is that I'm still learning C++ and I'm not Rinternals expert at
all! So I would love to get some feedback from you guys. Does this function,
-cppFuncall-, looks OK? in other words, am I doing/getting something wrong
here?
Thanks,
George G. Vega Yon
+1 (626) 381 8171
http://www.its.caltech.edu/~gvegayon/
_______________________________________________ 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
Thanks for the quick reply! What kind of errors are we talking about? I a new run I explicitly caused an error by passing a character vector, and had no memory leak (using Valgrind): cppFuncall(letters, fun) Error in cos(x[1]) : non-numeric argument to mathematical function If its not too much to ask, could you give an explicit example in which that happens (memory leak)? Just trying to learn here! Thanks, George G. Vega Yon +1 (626) 381 8171 http://www.its.caltech.edu/~gvegayon/
On Wed, Aug 3, 2016 at 11:29 AM, Kevin Ushey <kevinushey at gmail.com> wrote:
Also note that you definitely don't want to call `Rf_error` from a C++ context in general, as it will bypass any active C++ try-catch blocks, bypass destructors, and so on. You should call `Rcpp::stop` explicitly and use Rcpp attributes to ensure the try-catch block is automagically set up for you. On Wed, Aug 3, 2016 at 11:28 AM, Kevin Ushey <kevinushey at gmail.com> wrote:
The problem with your implementation is what happens if R throws an error. The R longjmp will cause any C++ objects on the stack to leak, their destructors not to run, and you'll essentially be in a bad place if you evaluate any R code that might return an error. (For example, suppose you had a file handle open, and then evaluated your R function using 'eval', but an R error was produced. That file handle would 'leak' and you wouldn't be able to recover it) You can instead use the `Rf_tryEval` or `Rf_tryEvalSilent` routines, but those don't respect active handlers (e.g. warning, message handlers) and so aren't sufficient for general use. Rcpp basically handles this by enclosing any expression to be evaluated in an R 'tryCatch' call, with error + interrupt handlers attached. This is, of course, slower since a lot more R code is being evaluated, but right now it's the only way to safely execute an R function in a C++ context while respecting all other active handlers. In short, the Rcpp::Function implementation is designed to be as safe + correct as possible, with the downside being that it's slower. However, we generally advise that you shouldn't call back to R too frequently from a C++ context, so that overhead should in most cases be not too bad. Best, Kevin On Wed, Aug 3, 2016 at 10:50 AM, George Vega Yon <g.vegayon at gmail.com>
wrote:
Hey there, Looking at some old R code that I have I found this C++ function that
allows
evaluating R-written functions within C++ using Rcpp. While this is no
news,
the neat thing of it is that it seems to be faster than Rcpp::Function. Using microbenchmark I compared using Rcpp::function vs my
implementation vs
calling the function from R itself and this is what I got
Unit: relative
expr min lq mean median uq max neval
cppFuncall(x, fun) 1.3 1.3 1.39 1.3 1.4 83 10000
RcppFuncall(x, fun) 7.2 7.1 7.13 6.9 6.8 89 10000
fun(x) 1.0 1.0 1.00 1.0 1.0 1 10000
So, on average, while Rcpp::Function took ~7 times the R call took, my
implementation took ~1.3 times. To be sure I was not breaking anything
I ran
the example using valgrind and there is no memory leak. The source code
for
the test follows:
-------- example_calling_r_functions.cpp ----
#include <Rinternals.h>
#include <Rcpp.h>
// [[Rcpp::export]]
SEXP cppFuncall(SEXP par, SEXP fn)
{
SEXP R_fcall, ans;
if(!isFunction(fn)) error("'fn' must be a function");
R_fcall = PROTECT(lang2(fn, R_NilValue));
SETCADR(R_fcall, par);
ans=eval(R_fcall, R_GlobalEnv);
UNPROTECT(1);
return ans;
}
using namespace Rcpp;
// [[Rcpp::export]]
SEXP RcppFuncall(NumericVector par, Function fn)
{
return fn(par);
}
/*** R
# R function to be called
fun <- function(x) {
-cos(x[1])*cos(x[2])*exp(-((x[1] - pi)^2 + (x[2] - pi)^2))
}
# Input data
set.seed(3331)
x <- runif(1e3)
# Benchmarking
library(microbenchmark)
microbenchmark(
cppFuncall(x, fun), RcppFuncall(x,fun), fun(x), times=1e4,
unit="relative", control = list(warmup=100)
)
*/
-------- example_calling_r_functions.cpp ----
I've asked around about how to make things faster for function calls in
Rcpp
but, from what I've been told it is difficult since the implementation
of
Rcpp::Function actually has to go back to R to work (or something like
that
:P). Now, this implementation, -cppFuncall-, has no problem when it
comes to
passing wrong arguments, e.g. if you pass a character vector to it R
will
complain but there won't be any system crash. One big difference is that here I'm relying on passing all the function's arguments in a single
object
while Rcpp::Function does not. Either way, if this is OK this could be a nice extra feature for Rcpp, I'm thinking of optimization routines (or
other
kinds of algorithms) that rely on calling R functions multiple times. The thing is that I'm still learning C++ and I'm not Rinternals
expert at
all! So I would love to get some feedback from you guys. Does this
function,
-cppFuncall-, looks OK? in other words, am I doing/getting something
wrong
here? Thanks, George G. Vega Yon +1 (626) 381 8171 http://www.its.caltech.edu/~gvegayon/
_______________________________________________ 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
-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20160803/45c11724/attachment-0001.html>
On 3 August 2016 at 11:38, George Vega Yon wrote:
| Thanks for the quick reply! What kind of errors are we talking about? I a new | run I explicitly caused an error by passing a character vector, and had no | memory leak (using Valgrind): | | cppFuncall(letters, fun) | Error in cos(x[1]) : non-numeric argument to mathematical function | | If its not too much to ask, could you give an explicit example in which that | happens (memory leak)? Just trying to learn here! You are misreading what Kevin said. You short ten-line example runs fine. We are not saying it has an error. What Kevin explained to you is that in the context of larger programs, possibly with inputs you don't know yet, some errors may occur. And both Rcpp:Function() and Rcpp::stop() can recover from that. Your example cannot. So by all means use it as a small (local) script if the few milliseconds matter to you. But think twice about using it in a larger context, or about promoting it as a general solution, and understand why we can't put it into Rcpp as is. Hth, Dirk
http://dirk.eddelbuettel.com | @eddelbuettel | edd at debian.org
The simplest demonstrating example I can think of:
---
#include <Rcpp.h>
using namespace Rcpp;
struct A { ~A() { Rprintf("~A()"); } };
// [[Rcpp::export]]
void ouch() {
A a;
Rf_error("ouch!");
}
/*** R
ouch()
*/
---
Call 'Rcpp::sourceCpp()' on that and you'll see:
Rcpp::sourceCpp('~/Desktop/Untitled.cpp')
ouch()
Error in ouch() : ouch! Note that the destructor was not called. Replace `Rf_error` with `Rcpp::stop` and you will see the destructor is called. It's possible that you won't have a memory leak per-se (if the memory is all allocated on the stack, maybe the runtime still knows to just clear the entire stack after something like this) but not running destructors is definitely a big problem. Cheers, Kevin
On Wed, Aug 3, 2016 at 12:22 PM, Dirk Eddelbuettel <edd at debian.org> wrote:
On 3 August 2016 at 11:38, George Vega Yon wrote: | Thanks for the quick reply! What kind of errors are we talking about? I a new | run I explicitly caused an error by passing a character vector, and had no | memory leak (using Valgrind): | | cppFuncall(letters, fun) | Error in cos(x[1]) : non-numeric argument to mathematical function | | If its not too much to ask, could you give an explicit example in which that | happens (memory leak)? Just trying to learn here! You are misreading what Kevin said. You short ten-line example runs fine. We are not saying it has an error. What Kevin explained to you is that in the context of larger programs, possibly with inputs you don't know yet, some errors may occur. And both Rcpp:Function() and Rcpp::stop() can recover from that. Your example cannot. So by all means use it as a small (local) script if the few milliseconds matter to you. But think twice about using it in a larger context, or about promoting it as a general solution, and understand why we can't put it into Rcpp as is. Hth, Dirk -- http://dirk.eddelbuettel.com | @eddelbuettel | edd at debian.org
Dirk, good point. This is a very simple function and if I add complexity at
the end there's no significant difference between calling -fun-,
-cppFuncall- and -RcppFuncall-. Just to make this thread more complete, if
I modify -fun- from
fun <- function(x) {
-cos(x[1])*cos(x[2])*exp(-((x[1] - pi)^2 + (x[2] - pi)^2))
}
to
fun <- function(x) {
w<-sapply(1:1e3,function(x) -cos(x[1])*cos(x[2])*exp(-((x[1] - pi)^2 +
(x[2] - pi)^2)))
1
}
Running the benchmark I get
Unit: relative
expr min lq mean median uq max neval
cppFuncall(x, fun) 1 1 1.044215 1 1 6.1 1000
RcppFuncall(x, fun) 1 1 1.018957 1 1 2.7 1000
fun(x) 1 1 1.000000 1 1 1.0 1000
Which is way more reasonable from what I was getting at first. No
significant difference overall.
Kevin, thanks for the example, now I get why isn't a good idea! This has
been very useful to me.
Best,
George G. Vega Yon
+1 (626) 381 8171
http://www.its.caltech.edu/~gvegayon/
On Wed, Aug 3, 2016 at 12:34 PM, Kevin Ushey <kevinushey at gmail.com> wrote:
The simplest demonstrating example I can think of:
---
#include <Rcpp.h>
using namespace Rcpp;
struct A { ~A() { Rprintf("~A()"); } };
// [[Rcpp::export]]
void ouch() {
A a;
Rf_error("ouch!");
}
/*** R
ouch()
*/
---
Call 'Rcpp::sourceCpp()' on that and you'll see:
Rcpp::sourceCpp('~/Desktop/Untitled.cpp')
ouch()
Error in ouch() : ouch! Note that the destructor was not called. Replace `Rf_error` with `Rcpp::stop` and you will see the destructor is called. It's possible that you won't have a memory leak per-se (if the memory is all allocated on the stack, maybe the runtime still knows to just clear the entire stack after something like this) but not running destructors is definitely a big problem. Cheers, Kevin On Wed, Aug 3, 2016 at 12:22 PM, Dirk Eddelbuettel <edd at debian.org> wrote:
On 3 August 2016 at 11:38, George Vega Yon wrote: | Thanks for the quick reply! What kind of errors are we talking about?
I a new
| run I explicitly caused an error by passing a character vector, and
had no
| memory leak (using Valgrind): | | cppFuncall(letters, fun) | Error in cos(x[1]) : non-numeric argument to mathematical function | | If its not too much to ask, could you give an explicit example in
which that
| happens (memory leak)? Just trying to learn here! You are misreading what Kevin said. You short ten-line example runs
fine.
We are not saying it has an error. What Kevin explained to you is that in the context of larger programs, possibly with inputs you don't know yet, some errors may occur. And both Rcpp:Function() and Rcpp::stop() can recover from that. Your example cannot. So by all means use it as a small (local) script
if the
few milliseconds matter to you. But think twice about using it in a
larger
context, or about promoting it as a general solution, and understand why
we
can't put it into Rcpp as is. Hth, 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/20160803/c9144d9a/attachment.html>