为了账号安全,请及时绑定邮箱和手机立即绑定

RCPP通过引用与按值传递

RCPP通过引用与按值传递

Go
海绵宝宝撒 2020-01-05 08:00:16
我通过第一次对Rcpp函数进行了测试inline,它解决了我的速度问题(感谢Dirk!): R:将负值替换为零初始版本如下所示:library(inline)cpp_if_src <- '  Rcpp::NumericVector xa(a);  int n_xa = xa.size();  for(int i=0; i < n_xa; i++) {    if(xa[i]<0) xa[i] = 0;  }  return xa;'cpp_if <- cxxfunction(signature(a="numeric"), cpp_if_src, plugin="Rcpp")但是,当调用时cpp_if(p),它会覆盖p输出,这与预期不符。因此,我认为它是通过引用传递的。所以我用以下版本修复了它:library(inline)cpp_if_src <- '  Rcpp::NumericVector xa(a);  int n_xa = xa.size();  Rcpp::NumericVector xr(a);  for(int i=0; i < n_xa; i++) {    if(xr[i]<0) xr[i] = 0;  }  return xr;'cpp_if <- cxxfunction(signature(a="numeric"), cpp_if_src, plugin="Rcpp")这似乎工作。但是现在当我将其重新加载到R中时,原始版本不再覆盖其输入(即,相同的精确代码现在也不会覆盖其输入):> cpp_if_src <- '+   Rcpp::NumericVector xa(a);+   int n_xa = xa.size();+   for(int i=0; i < n_xa; i++) {+     if(xa[i]<0) xa[i] = 0;+   }+   return xa;+ '> cpp_if <- cxxfunction(signature(a="numeric"), cpp_if_src, plugin="Rcpp")> > p [1] -5 -4 -3 -2 -1  0  1  2  3  4  5> cpp_if(p) [1] 0 0 0 0 0 0 1 2 3 4 5> p [1] -5 -4 -3 -2 -1  0  1  2  3  4  5我不是唯一尝试复制此行为并发现不一致结果的人:http://chat.stackoverflow.com/transcript/message/4357344#4357344这里发生了什么?
查看完整描述

2 回答

?
慕莱坞森

TA贡献1810条经验 获得超4个赞

它们的关键是“代理模型”-您xa的存储位置确实与原始对象相同,因此最终需要更改原始对象。


如果您不希望这样做,则应该做一件事:使用该clone()方法进行(深度)复制,或者显式创建一个新对象,将更改后的对象写入该对象。方法二不能做到这一点,您只需使用两个名称不同的变量,它们都是原始变量的“指针”(就代理模型而言)。


但是,当您将int向量(从R)传递给NumericVector类型时,隐式转换和复制会带来另外的复杂性:创建一个副本,然后不再更改原始副本。


这是一个更明确的示例,类似于我在教程或研讨会中使用的示例:


library(inline)

f1 <- cxxfunction(signature(a="numeric"), plugin="Rcpp", body='

  Rcpp::NumericVector xa(a);

  int n = xa.size();

  for(int i=0; i < n; i++) {

    if(xa[i]<0) xa[i] = 0;

  }

  return xa;

')


f2 <- cxxfunction(signature(a="numeric"), plugin="Rcpp", body='

  Rcpp::NumericVector xa(a);

  int n = xa.size();

  Rcpp::NumericVector xr(a);            // still points to a

  for(int i=0; i < n; i++) {

    if(xr[i]<0) xr[i] = 0;

  }

  return xr;

')


p <- seq(-2,2)

print(class(p))

print(cbind(f1(p), p))

print(cbind(f2(p), p))

p <- as.numeric(seq(-2,2))

print(class(p))

print(cbind(f1(p), p))

print(cbind(f2(p), p))

这就是我所看到的:


edd@max:~/svn/rcpp/pkg$ r /tmp/ari.r

Loading required package: methods

[1] "integer"

        p

[1,] 0 -2

[2,] 0 -1

[3,] 0  0

[4,] 1  1

[5,] 2  2

        p

[1,] 0 -2

[2,] 0 -1

[3,] 0  0

[4,] 1  1

[5,] 2  2

[1] "numeric"

       p

[1,] 0 0

[2,] 0 0

[3,] 0 0

[4,] 1 1

[5,] 2 2

       p

[1,] 0 0

[2,] 0 0

[3,] 0 0

[4,] 1 1

[5,] 2 2

edd@max:~/svn/rcpp/pkg$

因此,无论是从int到float还是从float到float都是非常重要的。



查看完整回答
反对 回复 2020-01-06
?
浮云间

TA贡献1829条经验 获得超3个赞

这很有趣。知道这一点的唯一方法是通过我猜想的调试器(或者您像Dirk一样编写程序包)。有没有办法将调试器附加到Rcpp函数?我正在考虑像Visual Studio调试器那样附加dll的方法,然后单击该dll即可进入代码。



查看完整回答
反对 回复 2020-01-06
  • 2 回答
  • 0 关注
  • 548 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信