[Rd] Fast way to call an R function from C++?

Kevin Ushey kev|nu@hey @end|ng |rom gm@||@com
Tue Jun 18 20:11:32 CEST 2019


Hi Jiefei,

Calling into R from C++ code is more complicated than one might think.
Please see Tomas Kalibera's post here:
https://developer.r-project.org/Blog/public/2019/03/28/use-of-c---in-packages/index.html

The Rcpp Function class is more expensive than a regular Rf_eval()
because it tries to prevent errors (longjmps) from jumping to the top
level, so that the C++ stack can be properly unwound. In addition,
your example also pays a cost for the indirect function calls used
with Rcpp attributes, since the generated R wrapper functions will
then use `.Call()` under the hood. You could also try to directly use
.Call() to avoid that extra R function call overhead.

Even then, R's dispatch system for primitive functions (like `^`) is
likely still going to be faster than what you get from the .Call()
interface, especially since some extra validation does occur when
using .Call(). In practice, that difference is usually negligible
outside of synthetic benchmarks.

Best,
Kevin

On Tue, Jun 18, 2019 at 10:41 AM King Jiefei <szwjf08 using gmail.com> wrote:
>
> Hi,
>
> I'm looking for a most efficient way to call an R function from C++ in a
> package. I know there are two functions (`R_forceAndCall` and `Rf_eval`)
> that can do the "call" part, but both are slow compared to calling the same
> function in R. I also try to use Rcpp and it is the worse one. Here is my
> test code:
>
> C++ code:
> ```
> // [[Rcpp::export]]
> SEXP C_test1(SEXP f, SEXP x) {
> SEXP call =PROTECT(Rf_lang2(f, x));
> SEXP val = R_forceAndCall(call, 1, R_GlobalEnv);
> UNPROTECT(1);
> return val;
> }
>
> // [[Rcpp::export]]
> SEXP C_test2(SEXP expr, SEXP env) {
> SEXP val = Rf_eval(expr, env);
> return val;
> }
>
> // [[Rcpp::export]]
> SEXP C_test3(SEXP f,SEXP x) {
> Function fun(f);
> return fun(x);
> }
> ```
>
> R code:
> ```
> testFunc<-function(x){
>   x=x^2
>   return(x)
> }
> evn=new.env()
> evn$x=x
> expr=quote(testFunc(evn$x))
>
> testFunc(evn$x)
> C_test1(testFunc, evn$x)
> C_test2(expr,evn)
> C_test3(testFunc,evn$x)
> ```
>
> For the results, I run each function 1,000,000 times:
>
>    - testFunc : 0.47 sec
>    - C_test1 : 2.46 sec
>    - C_test2 : 2.74 sec
>    - C_test3 : 18.86 sec
>
> It is clear to see that calling an R function in R is the fast one, it is
> about 5X faster than ` R_forceAndCall ` and ` Rf_eval`. the latter two
> functions have a similar performance and using Rcpp is the worst one. Is it
> expected? Why is calling an R function from C++ much slower than calling
> the function from R? Is there any faster way to do the function call in C++?
>
> Best,
> Jiefei
>
>         [[alternative HTML version deleted]]
>
> ______________________________________________
> R-devel using r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel



More information about the R-devel mailing list