【发布时间】:2019-10-20 08:20:08
【问题描述】:
我正在尝试通过使用foreach 来提高我的循环计算速度,但是我在这个循环中定义了一个简单的 Rcpp 函数。我将 Rcpp 函数保存为mproduct.cpp,然后调用该函数只需使用
sourceCpp("mproduct.cpp")
而Rcpp函数很简单,就是在C++中进行矩阵乘积:
// [[Rcpp::depends(RcppArmadillo, RcppEigen)]]
#include <RcppArmadillo.h>
#include <RcppEigen.h>
// [[Rcpp::export]]
SEXP MP(const Eigen::Map<Eigen::MatrixXd> A, Eigen::Map<Eigen::MatrixXd> B){
Eigen::MatrixXd C = A * B;
return Rcpp::wrap(C);
}
所以,Rcpp 文件中的函数是MP,指的是矩阵乘积。我需要执行以下foreach 循环(我已简化代码以进行说明):
foreach(j=1:n, .package='Rcpp',.noexport= c("mproduct.cpp"),.combine=rbind)%dopar%{
n=1000000
A<-matrix(rnorm(n,1000,1000))
B<-matrix(rnorm(n,1000,1000))
S<-MP(A,B)
return(S)
}
由于矩阵 A 和 B 的大小都很大,所以我想使用 foreach 来减轻计算成本。
但是,上面的代码不起作用,因为它向我提供了错误消息:
task 1 failed - "NULL value passed as symbol address"
我添加.noexport= c("mproduct.cpp") 的原因是听从解决类似问题的人的一些建议 (Can't run Rcpp function in foreach - "NULL value passed as symbol address")。但不知何故,这并不能解决我的问题。
所以我尝试将我的 Rcpp 函数安装为库。我使用了以下代码:
Rcpp.package.skeleton('mp',cpp_files = "<my working directory>")
但它会返回一条警告消息:
The following packages are referenced using Rcpp::depends attributes however are not listed in the Depends, Imports or LinkingTo fields of the package DESCRIPTION file: RcppArmadillo, RcppEigen
所以当我尝试使用安装我的包时
install.packages("<my working directory>",repos = NULL,type='source')
我收到了警告信息:
Error in untar2(tarfile, files, list, exdir, restore_times) :
incomplete block on file
In R CMD INSTALL
Warning in install.packages :
installation of package ‘C:/Users/Lenovo/Documents/mproduct.cpp’ had non-zero exit status
那么有人可以帮我解决如何解决 1) 使用带有 Rcpp 函数 MP 的 foreach,或者 2) 将 Rcpp 文件安装为一个包?
非常感谢大家。
【问题讨论】:
-
Rcpp 代码是玩具示例还是您的真实代码?我怀疑您是否可以通过使用 RcppEigen(或 RcppArmadillo)获得比
%*%更多的收益。但是,当您需要使用其中一个包时,您应该决定要使用哪一个(您当前的代码根本不使用 Armadillo ...)。之后,使用那个包中的*.package.skeleton()函数。 -
欢迎来到 StackOverflow,Rico。 Ralf 是正确的:其他包也有你应该使用的骨架生成器。
-
@RalfStubner 感谢您的评论。 Rcpp 代码是我的真实代码,
foreach代码是我的玩具代码,说明当 Rcpp 函数位于内部时,我正在尝试执行foreach循环。很抱歉,但仍然没有得到你的两点:1)我应该如何使用 RcppEigen 改进Eigen::MatrixXd C = A * B?和 2) 我应该如何修改我的Rcpp代码以便我只能使用 RcppEigen 包? -
@DirkEddelbuettel 谢谢。但我对 Rcpp 很陌生,我需要做的就是使矩阵乘积 AB 尽可能快。我不确定哪些包有骨架生成器。
-
Rico:请阅读(至少)Rcpp Introduction 小插图;它会清除很多事情。它还提到了一点 RcppArmadillo。 Ralf 和我指出了该包中的函数
RcppArmadillo.package.skeleton()(或在 RcppEigen 中对称)。最后,我们试图向您解释 R 已经使用了相同的 LAPACK 矩阵乘法代码。仅通过从 C++ 调用它,您将获得很少甚至一无所获——但您可以通过一些基准测试自己看看。