使用 Rcpp 在 C++ 函数的 R 中使用 for 循环的内存问题

Posted

技术标签:

【中文标题】使用 Rcpp 在 C++ 函数的 R 中使用 for 循环的内存问题【英文标题】:Mermory issue by using a for loop in R of C++ function using Rcpp 【发布时间】:2018-12-06 11:00:34 【问题描述】:

使用带有 Rcpp 函数的 for 循环有一些不清楚的地方。这是一个应该有所帮助的简单示例:

这是我在文件test_cpp.cpp中的cpp代码

#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::mat test_Cpp(int n,
                   arma::vec my_vec,
                   Rcpp::List my_list,
                   int mat_size,
                   double lambda,
                   double beta) 
  //  Matrix of mat_size rows & mat_size columns (filled with 0)
  arma::mat matrix_out(mat_size, mat_size) ;
  for (int it = 0 ; it < n ; ++it) 
    arma::mat temp_mat_flux_convol = my_list[it] ;
    if (my_vec[it] != 0) 
      matrix_out += lambda * my_vec[it] * beta * temp_mat_flux_convol ;
    
  
  return matrix_out ;
 

那么从R代码来看,为什么res1res2在“无用”for循环中使用时不同,而没有for循环时相同?我猜有一个段错误的东西,但我没有得到它!

library(Rcpp)
library(RcppArmadillo)
sourceCpp(file = "src/test_cpp.cpp")
set.seed(123)
ls_rand = lapply(1:10, function(x) matrix(rnorm(9), ncol=3))


for(i in 1:1)
  res1 <- test_Cpp(n = 10,
                my_vec = 1:100,
                my_list = ls_rand,
                mat_size = 3,
                lambda =  24,
                beta = 0.4)

  res2 <- test_Cpp(n = 10,
                my_vec = 1:100,
                my_list = ls_rand,
                mat_size =  3,
                lambda = 24,
                beta = 0.4)

all.equal(res1, res2)
res1 ; res2 # here res2 is twice res1 !!!

## Without for loop
res1 <- test_Cpp(n = 10,
                my_vec = 1:100,
                my_list = ls_rand,
                mat_size = 3,
                lambda =  24,
                beta = 0.4)
res2 <- test_Cpp(n = 10,
              my_vec = 1:100,
              my_list = ls_rand,
              mat_size =  3,
              lambda = 24,
              beta = 0.4)

all.equal(res1, res2)
res1 ; res2 # here res1 and res2 are the same!

【问题讨论】:

【参考方案1】:

错误就在这里:

  //  Matrix of mat_size rows & mat_size columns (filled with 0)
  arma::mat matrix_out(mat_size, mat_size) ;

documentation 说:

mat(n_rows, n_cols)(内存未初始化) mat(n_rows, n_cols, fill_type)(内存已初始化)

因此,如果您将代码更改为

  //  Matrix of mat_size rows & mat_size columns (filled with 0)
  arma::mat matrix_out(mat_size, mat_size, arma::fill::zeros) ;

评论实际上是正确的,问题就消失了。

【讨论】:

是的。极好的。我整天用头撞墙!

以上是关于使用 Rcpp 在 C++ 函数的 R 中使用 for 循环的内存问题的主要内容,如果未能解决你的问题,请参考以下文章

如何分析 Rcpp 代码(在 linux 上)

优化 R 代码 - Rcpp

(Rcpp)armadillos abs() 函数在 std::abs 工作时与 c++ double 一起使用时输出错误值

将 C++ 函数用作由导出的 Rcpp 函数调用的另一个 C++ 函数的参数

如何从 Rcpp 中的另一个函数调用一个函数?

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