创建一个与其他 Rcpp 包具有依赖关系的简单 Rcpp 包
Creating a simple Rcpp package with dependency with other Rcpp package
我试图通过使用 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>")
但它 returns 给我一条警告消息:
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) 使用 foreach
和 Rcpp 函数 MP
,或 2) 将 Rcpp 文件安装为一个包吗?
非常感谢大家
第一步是确保优化正确。对我来说,这 不是 的情况,因为这个简单的基准显示:
set.seed(42)
n <- 1000
A<-matrix(rnorm(n*n), n, n)
B<-matrix(rnorm(n*n), n, n)
MP <- Rcpp::cppFunction("SEXP MP(const Eigen::Map<Eigen::MatrixXd> A, Eigen::Map<Eigen::MatrixXd> B){
Eigen::MatrixXd C = A * B;
return Rcpp::wrap(C);
}", depends = "RcppEigen")
bench::mark(MP(A, B), A %*% B)[1:5]
#> # A tibble: 2 x 5
#> expression min median `itr/sec` mem_alloc
#> <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt>
#> 1 MP(A, B) 277.8ms 278ms 3.60 7.63MB
#> 2 A %*% B 37.4ms 39ms 22.8 7.63MB
所以对我来说,通过 %*%
的矩阵积比通过 RcppEigen 的矩阵积快几倍。但是,当您使用 Windows 时,我将 Linux 与 OpenBLAS 一起用于矩阵运算,这通常意味着参考 BLAS 进行矩阵运算。 可能 RcppEigen 在您的系统上更快。我不确定 Windows 用户获得更快的 BLAS 实现有多困难(https://csgillespie.github.io/efficientR/set-up.html#blas-and-alternative-r-interpreters 可能包含一些指针),但我建议花一些时间对此进行调查。
现在,如果您得出的结论是您的代码中确实需要 RcppEigen 或 RcppArmadillo 并且想要将该代码放入一个包中,您可以执行以下操作。代替 Rcpp::Rcpp.package.skeleton()
使用 RcppEigen::RcppEigen.package.skeleton()
或 RcppArmadillo::RcppArmadillo.package.skeleton()
为基于 RcppEigen
或 RcppArmadillo
, 分别.
我试图通过使用 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>")
但它 returns 给我一条警告消息:
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) 使用 foreach
和 Rcpp 函数 MP
,或 2) 将 Rcpp 文件安装为一个包吗?
非常感谢大家
第一步是确保优化正确。对我来说,这 不是 的情况,因为这个简单的基准显示:
set.seed(42)
n <- 1000
A<-matrix(rnorm(n*n), n, n)
B<-matrix(rnorm(n*n), n, n)
MP <- Rcpp::cppFunction("SEXP MP(const Eigen::Map<Eigen::MatrixXd> A, Eigen::Map<Eigen::MatrixXd> B){
Eigen::MatrixXd C = A * B;
return Rcpp::wrap(C);
}", depends = "RcppEigen")
bench::mark(MP(A, B), A %*% B)[1:5]
#> # A tibble: 2 x 5
#> expression min median `itr/sec` mem_alloc
#> <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt>
#> 1 MP(A, B) 277.8ms 278ms 3.60 7.63MB
#> 2 A %*% B 37.4ms 39ms 22.8 7.63MB
所以对我来说,通过 %*%
的矩阵积比通过 RcppEigen 的矩阵积快几倍。但是,当您使用 Windows 时,我将 Linux 与 OpenBLAS 一起用于矩阵运算,这通常意味着参考 BLAS 进行矩阵运算。 可能 RcppEigen 在您的系统上更快。我不确定 Windows 用户获得更快的 BLAS 实现有多困难(https://csgillespie.github.io/efficientR/set-up.html#blas-and-alternative-r-interpreters 可能包含一些指针),但我建议花一些时间对此进行调查。
现在,如果您得出的结论是您的代码中确实需要 RcppEigen 或 RcppArmadillo 并且想要将该代码放入一个包中,您可以执行以下操作。代替 Rcpp::Rcpp.package.skeleton()
使用 RcppEigen::RcppEigen.package.skeleton()
或 RcppArmadillo::RcppArmadillo.package.skeleton()
为基于 RcppEigen
或 RcppArmadillo
, 分别.