gpt4 book ai didi

c++ - Rcpp 函数比相同的 R 函数慢

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:10:35 26 4
gpt4 key购买 nike

我一直在编写一个 R 函数来计算关于某些分布的积分,请参见下面的代码。

EVofPsi = function(psi, probabilityMeasure, eps=0.01, ...){

distFun = function(u){
probabilityMeasure(u, ...)
}
xx = yy = seq(0,1,length=1/eps+1)
summand=0

for(i in 1:(length(xx)-1)){
for(j in 1:(length(yy)-1)){
signPlus = distFun(c(xx[i+1],yy[j+1]))+distFun(c(xx[i],yy[j]))
signMinus = distFun(c(xx[i+1],yy[j]))+distFun(c(xx[i],yy[j+1]))
summand = c(summand, psi(c(xx[i],yy[j]))*(signPlus-signMinus))
}
}
sum(summand)
}

它工作正常,但速度很慢。经常听说用 C++ 等编译语言重新编写函数会加快速度,尤其是因为上面的 R 代码涉及双循环。我也是,使用 Rcpp:

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
double EVofPsiCPP(Function distFun, Function psi, int n, double eps) {

NumericVector xx(n+1);
NumericVector yy(n+1);
xx[0] = 0;
yy[0] = 0;

// discretize [0,1]^2
for(int i = 1; i < n+1; i++) {
xx[i] = xx[i-1] + eps;
yy[i] = yy[i-1] + eps;
}

Function psiCPP(psi);
Function distFunCPP(distFun);
double signPlus;
double signMinus;
double summand = 0;

NumericVector topRight(2);
NumericVector bottomLeft(2);
NumericVector bottomRight(2);
NumericVector topLeft(2);

// compute the integral
for(int i=0; i<n; i++){
//printf("i:%d \n",i);
for(int j=0; j<n; j++){
//printf("j:%d \n",j);
topRight[0] = xx[i+1];
topRight[1] = yy[j+1];
bottomLeft[0] = xx[i];
bottomLeft[1] = yy[j];
bottomRight[0] = xx[i+1];
bottomRight[1] = yy[j];
topLeft[0] = xx[i];
topLeft[1] = yy[j+1];
signPlus = NumericVector(distFunCPP(topRight))[0] + NumericVector(distFunCPP(bottomLeft))[0];
signMinus = NumericVector(distFunCPP(bottomRight))[0] + NumericVector(distFunCPP(topLeft))[0];
summand = summand + NumericVector(psiCPP(bottomLeft))[0]*(signPlus-signMinus);
//printf("summand:%f \n",summand);
}
}
return summand;
}

我很高兴,因为这个 C++ 函数运行良好。但是,当我测试这两个函数时,C++ 函数运行速度较慢:

sourceCpp("EVofPsiCPP.cpp")
pFGM = function(u,theta){
u[1]*u[2] + theta*u[1]*u[2]*(1-u[1])*(1-u[2])
}
psi = function(u){
u[1]*u[2]
}
print(system.time(
for(i in 1:10){
test = EVofPsi(psi, pFGM, 1/100, 0.2)
}
))
test

print(system.time(
for(i in 1:10){
test = EVofPsiCPP(psi, function(u){pFGM(u,0.2)}, 100, 1/100)
}
))

那么,周围有好心的专家愿意为我解释一下吗?我是不是像猴子一样编码,有没有办法加快该功能?此外,我还有第二个问题。实际上,我可以用 SEXP 替换输出类型 double,也可以用 SEXP 替换参数类型 Function,它似乎没有改变任何东西。那有什么区别呢?

非常感谢您,吉尔达斯

最佳答案

其他人已经在评论中回答了。所以我只强调一点:回调 R 函数是昂贵的,因为我们需要对错误处理格外小心。仅仅在 C++ 中使用循环并调用 R 函数并不是在 C++ 中重写代码。尝试将 psipFGM 重写为 C++ 函数,并在此处报告发生的情况。

您可能会争辩说您失去了一些灵 active 并且您不能再使用任何 R 函数。对于这种情况,我建议使用某种混合解决方案,您已经在 C++ 中实现了最常见的情况,否则回退到 R 解决方案。

至于另一个问题,SEXP 是一个 R 对象。这是 R API 的一部分。它可以是任何东西。当您从它创建一个 Function 时(就像在创建一个带有 Function 参数的函数时为您隐式完成的那样)时,您可以保证这确实是一个 R 函数。开销非常小,但是在代码表达能力方面的 yield 是巨大的。

关于c++ - Rcpp 函数比相同的 R 函数慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17958168/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com