内存在简单的Rcpp函数中泄漏

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了内存在简单的Rcpp函数中泄漏相关的知识,希望对你有一定的参考价值。

我正在开发一个R中的包,我想转换为Rcpp以获得更好的性能。我是Rcpp的新手(和C ++一样。)我的问题是,如果我用一组参数运行它多次,我编写的Rcpp函数工作正常,但是如果我尝试将它循环遍历许多参数组合,它会弹出内存泄漏并导致R会话中止。

这是R中的代码,它可以很好地适用于我抛出的任何测试:

raw_noise <- function(timesteps, mu, sigma, phi) {
   delta <- mu * (1 - phi)
   variance <- sigma^2 * (1 - phi^2)
   noise <- vector(mode = "double", length = timesteps)
   noise[1] <- c(rnorm(1, mu, sigma))
   for (i in (1:(timesteps - 1))) {
     noise[i + 1] <- delta + phi * noise[i] + rnorm(1, 0, sqrt(variance))
  }
   return(noise)
}

这是Rcpp中的代码,使用三个Rcpp sugar functions(pow,sqrt,rnorm):

NumericVector raw_noise(int timesteps, double mu, double sigma, double phi) {
  double delta = mu * (1 - phi);
  double variance = pow(sigma, 2.0) * (1 - pow(phi, 2.0));
  NumericVector noise(timesteps);
  noise[0] = R::rnorm(mu, sigma);
  for(int i = 0; i < timesteps; ++i) {
    noise[i+1] = delta + phi*noise[i] + R::rnorm(0, sqrt(variance));
  }
  return noise;
}

让我感到困惑的是这段代码运行没有问题:

library(purrr)
rerun(10000, raw_noise(timesteps = 30, mu = 0.5, sigma = 0.2, phi = 0.3))

但是当我运行这段代码时:

test_loop <- function(timesteps, mu, sigma, phi, replicates) {
  params <- cross_df(list(timesteps = timesteps, phi = phi, mu = mu, sigma = 
sigma))
  for (i in 1:nrow(params)) {
    print(params[i,])
    pmap(params[i,], raw_noise)
  }
}
library(purrr)
test_loop(timesteps=c(5, 6, 7, 8, 9, 10), mu=c(0.2, 0.5), sigma=c(0.2, 0.5),
      phi=c(0, 0.1))

R会话通常会中止并且RStudio完全崩溃。但有时我设法在R会话中止之前捕获此错误消息:

匹配错误(x,table,nomatch = 0L):GC遇到一个SEXP类型未知的节点(0x10db7af50):NEWSXP at memory.c:1692

据我所知,NEWSXP是R中的一种奇特的对象类型,并不经常出现。发生的事情在我看来就像是内存泄漏,但我不确定如何修复它。就像我说的那样,我一般都是Rcpp和C ++的新手,所以我很欣赏任何朝着正确方向的推动。

答案

你有一个越界错误:

for(int i = 0; i < timesteps; ++i)

原因

noise[i+1]

超过定义的范围,因为C ++索引从0开始而不是1。


例如,0timesteps - 1的长度为timesteps,因此可以。

0timesteps的长度为timesteps + 1

如果将noise[i+1]更改为noise(i+1),可以看到这一点,Error in raw_noise(100, 2, 3, 0.2) : Index out of bounds: [index=100; extent=100]. 对请求的索引执行边界检查。

NumericVector raw_noise(int timesteps, double mu, double sigma, double phi) {
  double delta = mu * (1 - phi);
  double variance = pow(sigma, 2.0) * (1 - pow(phi, 2.0));
  NumericVector noise(timesteps);
  noise[0] = R::rnorm(mu, sigma);

  // change here
  for(int i = 0; i < timesteps - 1; ++i) { // 1 less time step

    noise[i+1] = delta + phi*noise[i] + R::rnorm(0, sqrt(variance));
  }
  return noise;
}

要解决此问题,请进行以下更改:

qazxswpoi

以上是关于内存在简单的Rcpp函数中泄漏的主要内容,如果未能解决你的问题,请参考以下文章

如何使用模块化代码片段中的LeakCanary检测内存泄漏?

在Rcpp函数中替换Rcpp :: List的元素是否是内存安全的?

避免android片段中内存泄漏的最佳方法是啥

在片段中保存活动实例:是否会导致内存泄漏?

自定义无内存泄漏的Handler内部类

FragmentStatePagerAdapter 内存泄漏(带有 viewpager 的嵌套片段)