在RCpp中完成或销毁内存中的xptr矩阵

时间:2014-01-18 15:01:07

标签: c++ r memory matrix rcpp

这是关于使用xptr在内存中存储和检索矩阵的前一个问题here的后续内容 - 这是非常好的回答 - 非常感谢你。现在我可以使用xptr在内存中创建和检索矩阵如何正确地完成/销毁对象。 Rcpp对象应该在删除时自动进行垃圾收集,但是当我创建指针时,如果我在R中删除它,我必须运行gc()两次以恢复内存,例如。

// This function wraps the matrix an returns a pointer
// [[Rcpp::export]]
SEXP writeMemObject(NumericMatrix mat)
{
  XPtr<NumericMatrix> ptr(new NumericMatrix(mat), true);
  return ptr;
}

检索矩阵的函数(来自上一个答案)

// [[Rcpp::export]]
NumericMatrix getMemObject(SEXP ptr)
{
  XPtr<NumericMatrix> out(ptr);
  return *out;
}

然后在R

createMemMatrix <- function(dims){
  ptr <- writeMemObject(matrix(runif(prod(dims)), nc = dims[2]))
  return(ptr)
}

ptr <- createMemMatrix(c(1e4, 1e4))
#mat <- getMemObject(ptr) # this works but not run here
rm(ptr);
gc(); # nothing seems to happen in memory
gc(); # memory is freed (visible in system monitor)

上一个问题的答案中提到了bigmemory R包,他们的对象立即释放了内存

# In R
require(bigmemory)
# be careful this is a large matrix
x1 <- big.matrix(ncol = 1e4, nrow = 1e4)
x1[,] <- runif(1e8)
rm(x1)
gc() # memory is freed right away (visible on system monitor)

我尝试了bigmemory包中使用的类似方法,并在创建时注册指针:

// C function for destroying the matrix behind the pointer
void destroyItem(SEXP ptr)
{
  NumericMatrix *pm=(NumericMatrix*)(R_ExternalPtrAddr(ptr));
  delete pm;
  R_ClearExternalPtr(ptr);
}

// This function wraps the matrix an returns a pointer
// [[Rcpp::export]]
SEXP writeMemObject(NumericMatrix mat)
{
  XPtr<NumericMatrix> ptr(new NumericMatrix(mat), true);
  R_RegisterCFinalizerEx(ptr, (R_CFinalizer_t) destroyItem, (Rboolean) TRUE);
  return ptr;
}

但这并没有什么不同。 bigmemory包非常棒,但我认为使用Rcpp对象是值得的,因为可以在内存中存储各种各样的对象。

1 个答案:

答案 0 :(得分:5)

R有一代分类垃圾收集器,例如参见this section of R internals。因此,每次调用gc()可能不会触发完整的集合。

另请注意,XPtr已注册了调用delete的终结器,因此您无需注册destryItem终结器。除delete指针外,您只需要注册一个终结器来执行某些操作。幸运的是,由于你的R_ClearExternalPtr,你没有得到双重删除,但这无论如何都是危险的。