我正在阅读许多参考文献中的非常通用的建议,包括来自Rcpp主页和stackoverflow中的其他帖子的介绍,例如Calling an R function using inline and rcpp is still just as low as original R。
我担心的是,当我们构建一个CRAN包时,应该在R中声明后验分布的评估(是的,我是贝叶斯)。主算法是用Rcpp编写的,NumericMatrix sampling(NumericVector x, Function func)
。
我试过(1)简单地输入R函数和(2)定义一个带有cppFunction
的对象来传递给cpp脚本。当然,它没有预期的性能差异。
所以我的主要问题应该是
如果用户提供了C / C ++中的表单,是否有其他方法可以将evaluting函数
func
作为输入参数传递给我们的通用Rcpp脚本?
我一直在努力解决这个问题很长一段时间 - 看看Rcpp画廊及其相关项目。由于我们的目标受众在编码方面的文化程度远低于我,因此我们希望指定一个函数不应该超过简单地编写内联函数。我们非常感谢任何建议。
答案 0 :(得分:4)
我试图创建一个受RcppDE启发的例子。
首先我们定义一个C ++函数,它调用n次a&#34; sum&#34;函数作为参数传递。给定的函数可以是R函数或包含函数指针的xptr<>
代码:
require(Rcpp)
# C++ function which calls a given "sum" function n-times.
# The passed function can be an R function or
# an xptr wrapping a function pointer.
sourceCpp(code="
#include <Rcpp.h>
typedef double (*sumFnPtr)(Rcpp::NumericVector);
// [[Rcpp::export]]
Rcpp::NumericVector callSumFunctionNTimes(SEXP sumFn, Rcpp::NumericVector toSum,int times){
Rcpp::NumericVector output(times);
switch (TYPEOF(sumFn)){
case EXTPTRSXP:
{
Rcpp::XPtr<sumFnPtr> xptr = Rcpp::as< Rcpp::XPtr<sumFnPtr> >(sumFn);
for(int i = 0; i < times; i++){
output[i] = (*(xptr))(toSum);
}
break;
}
// we suppose is a R function
default:
{
Rcpp::Function fn = Rcpp::as<Rcpp::Function>(sumFn);
for(int i = 0; i < times; i++)
output[i] = Rcpp::as<double>( fn(toSum) );
break;
}
}
return output;
}
")
然后,在C ++中我们定义&#34; mySum&#34;函数和另一个函数返回xptr<>
包装它
代码:
require(Rcpp)
# Here we define the sum function in C++ and we also
# define a function returning a xptr wrapping the function
sourceCpp(code="
#include <Rcpp.h>
typedef double (*sumFnPtr)(Rcpp::NumericVector);
// [[Rcpp::export]]
double mySum(Rcpp::NumericVector toSum){
double s = 0;
for(int i = 0; i < toSum.length(); i++){
s += toSum[i];
}
return s;
}
// [[Rcpp::export]]
SEXP getSumFunctionPtr(){
return Rcpp::XPtr<sumFnPtr>(new sumFnPtr(&mySum));
}
")
最后,我们定义了一个函数,它计算C ++中的所有总和(即没有接收函数作为参数)。代码:
require(Rcpp)
sourceCpp(code="
#include <Rcpp.h>
// [[Rcpp::export]]
Rcpp::NumericVector doEverythingInCpp(Rcpp::NumericVector toSum, int times){
Rcpp::NumericVector output(times);
for(int i = 0; i < times; i++){
double s = 0;
for(int j =0; j < toSum.length();j++){
s += toSum[j];
}
output[i] = s;
}
}
")
让我们测试在以下情况下会发生什么:
xptr<>
包裹了100万次代码:
# TEST 1
system.time(callSumFunctionNTimes(sum,1:100,1e6))
# user system elapsed
# 13.45 0.00 13.45
# TEST 2
system.time(callSumFunctionNTimes(mySum,1:100,1e6))
# user system elapsed
# 13.97 0.00 13.97
# TEST 3
mySumFunctionnPtr <- getSumFunctionPtr()
system.time(callSumFunctionNTimes(mySumFunctionnPtr,1:100,1e6))
# user system elapsed
# 0.28 0.00 0.29
# TEST 4
system.time(doEverythingInCpp(1:100,1e6))
# user system elapsed
# 0.27 0.00 0.27
正如您所看到的,当我们将编译函数(即包含在R <-> C++
中的函数指针)传递给C ++时,xptr<>
转换开销消失了,实际上TEST 3和4基本相同性能