【问题标题】:Why is this Rcpp function alter variables outside of its own scope?为什么这个 Rcpp 函数会改变它自己范围之外的变量?
【发布时间】:2016-02-16 18:05:42
【问题描述】:

我正在运行来自http://markovjumps.blogspot.com/2011/12/r-array-to-rcpparmadillo-cube.html 的以下示例代码,它说明了如何将 R 数组转换为 RcppArmadillo 立方体。代码如下

require(inline)
require(RcppArmadillo)

src <- '
       using namespace Rcpp;

       NumericVector vecArray(myArray);
       IntegerVector arrayDims = vecArray.attr("dim");

       arma::cube cubeArray(vecArray.begin(), arrayDims[0], arrayDims[1], arrayDims[2], false);

       //change one element in the array/cube
       cubeArray(0,0,0) = 518;  

       return(wrap(cubeArray));  
'

readCube = cxxfunction(signature(myArray="numeric"),body=src, plugin="RcppArmadillo")

set.seed(345)
testArray = array(rnorm(8), dim=c(2,2,2))
print(testArray[1,1,1])
# -0.7849082
readCube(testArray)[1,1,1]
# 518
print(testArray)[1,1,1]
# 518

可以看出,testArray 已被更改。但是,我不太明白为什么会发生这种情况。

我对该问题进行了一些搜索,并在http://arma.sourceforge.net/docs.html#Cube 中发现“使用可写辅助(外部)内存中的数据创建多维数据集,其中 ptr_aux_mem 是指向内存的指针。默认情况下,多维数据集分配自己的内存并复制辅助内存中的数据(为了安全)。但是,如果将 copy_aux_mem 设置为 false,则多维数据集将直接使用辅助内存(即不复制);这更快,但除非您知道自己在做什么,否则可能很危险!”

所以我将 false 更改为 true,问题就消失了。但是,我仍然感到困惑,因为原始代码创建了一个新的 NumericVector vecArray 并且 vecArray.begin() 应该引用该新 NumericVector 对象的内存,而不是函数输入 myArray。我觉得改变 cubeArray 应该只改变 vecArray 而不是 myArray。

【问题讨论】:

  • 您可能想了解clone(),例如:stackoverflow.com/questions/11300048/…
  • 谢谢!这完美地回答了我的问题。
  • 我建议将您的解决方案作为答案发布,而不是编辑问题。

标签: r rcpp


【解决方案1】:

感谢 Dirk,现在我知道我被困在哪里了。以下是我自己的解决方案:

这个问题可以通过使用 clone() 或创建一个新的犰狳立方体对象来解决。两种解决方案如下。

// Using clone()
src <- '
       using namespace Rcpp;

       NumericVector vecArray(clone(myArray));
       IntegerVector arrayDims = vecArray.attr("dim");

       arma::cube cubeArray(vecArray.begin(), arrayDims[0], arrayDims[1], arrayDims[2], false);

       //change one element in the array/cube
       cubeArray(0,0,0) = 518;  

       return(wrap(cubeArray));  
'

readCube = cxxfunction(signature(myArray="numeric"),body=src, plugin="RcppArmadillo")

// Not using clone()
src <- '
       using namespace Rcpp;

       NumericVector vecArray(myArray);
       IntegerVector arrayDims = vecArray.attr("dim");

       arma::cube cubeArray(vecArray.begin(), arrayDims[0], arrayDims[1], arrayDims[2]);

       //change one element in the array/cube
       cubeArray(0,0,0) = 518;  

       return(wrap(cubeArray));  
'

readCube = cxxfunction(signature(myArray="numeric"),body=src, plugin="RcppArmadillo")

请注意,您不想在使用 clone() 的同时还创建一个新的立方体对象,因为它在内存中效率不高。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-04
    相关资源
    最近更新 更多