删除函数环境中C++输入 R 对象



我在R函数中有一个Rcpp函数。R 函数生成一些对象(例如一个大列表(并将其提供给 Rcpp 函数。在 Rcpp 函数中,我处理 R 对象,将结果加载到多个C++类中。现在,R 对象变得毫无用处。我想清除 R 对象,以便为主要算法创建一个内存充足的环境。

这个想法是:

// [[Rcpp::export]]
void cppFun(List structuredData)
{
// copy structuredData to C++ classes
// Now I want structuredData gone to save memory
// main algorithms ...
}
/***R
rFun(input)
{
# R creates structuredData from input
cppFun(structuredData)
}
*/

我尝试在C++中调用 R 的"rm((",但它只能识别 R 全局环境中的对象名称。例如:

// [[Rcpp::export]]
void cppFun()
{
Language("rm", "globalDat").eval(); 
Language("gc").eval();
}
/***R
globalDat = 1:10
ls() # shows "globalDat" is created.
cppFun() # shows "globalDat" is no longer in the environment.
ls()
*/

但是,以下方法不起作用:

// [[Rcpp::export]]
void cppFun()
{
Language("rm", "localDat").eval(); 
Language("gc").eval();
}
/***R
rFun <- function (x)
{
locDat = x
ls() //  shows "x" and "locDat" are created
cppFun()
ls()
}
globalDat = 1:10
ls() # shows "globalDat" is created.
rFun(globalDat) # it will print "x","locDat" twice and a warning message: In rm("localDat") : object 'localDat' not found
locDat = globalDat
rFun(globalDat) # this will still remove "locDat" from the global environment.
*/

我是否走在实现目标的正确轨道上?有没有更好的方法?

谢谢!

想到了一个黑客解决方案:

  1. 编写一个 shell 类,包装对所有必需C++结构化数据类的引用。

  2. 在 R 函数中,(i( 处理输入;(ii( 将结构化的 R 数据提供给 Rcpp 函数;(iii( 在 Rcpp 函数中,newshell 类对象,加载结构化的 R 数据;(iv(memcpyshell 类指针指向double(8 个字节,如果是 32 位系统,请使用int(;(v( 归还double;(vi( 将double从 R 函数中返回。现在,结构化的 R 对象死亡,而newed C++ shell 对象仍然存在。调用gc()进行垃圾回收。

  3. double馈送到主C++/Rcpp 函数。memcpy此双精度到外壳类指针。 在函数返回之前delete外壳类指针。

测试表明上述工作。刚刚找到"外部指针"或为类似目的设计的Rcpp::XPtr

Rcpp中,按照这些思路做一些事情将被称为反模式或高度适得其反。为什么这是有问题的,因为Rcpp在将 R 对象移动到 C++ 时执行浅拷贝,这意味着R对象与实例化的C++对象共享其内存分配。如果要在C++对象引用 R 对象时删除对象,则可能会在此过程的后期遇到麻烦,因为可能会发生分段错误(段错误(。

现在,如果您打算从R对象到C++结构进行深层复制,这不会那么有害。执行深层复制时,数据引用原始R对象。但是,这不是Rcpp的默认架构。

话虽如此,我强烈建议不要在过程中删除对象。如果您确实内存紧张,请尝试"分块"/更多地划分数据,对数据库执行操作,购买额外的 RAM 或等待ALTREP

最新更新