Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Rcpp可以提高速度吗_R_Rcpp - Fatal编程技术网

使用Rcpp可以提高速度吗

使用Rcpp可以提高速度吗,r,rcpp,R,Rcpp,最近,我在Rcpp软件包上遇到了麻烦,看到了它在速度方面的巨大改进,尤其是在循环方面。我正在编写一个模拟程序,不断在5D阵列上执行矩阵代数。一个例子如下所示: library(rbenchmark) Mat<- assign("Mat",array(10,c(10,10,9,4,9))) Mat2<-matrix(c(runif(16,0,1)),nrow=4,ncol=4) FuncR<-function(x){ for(i in 1:dim(Mat)[1]){

最近,我在Rcpp软件包上遇到了麻烦,看到了它在速度方面的巨大改进,尤其是在循环方面。我正在编写一个模拟程序,不断在5D阵列上执行矩阵代数。一个例子如下所示:

library(rbenchmark)
Mat<- assign("Mat",array(10,c(10,10,9,4,9)))
Mat2<-matrix(c(runif(16,0,1)),nrow=4,ncol=4)
FuncR<-function(x){
  for(i in 1:dim(Mat)[1]){
    for(j in 1:dim(Mat)[2]){
      for(loc in 1:dim(Mat)[3]){
        for(Yr in 1:dim(Mat)[5]){
          Mat[i,j,loc,,Yr]<<-floor(x%*%Mat[i,j,loc,,Yr])
        }
      }
    }
  }
}
benchmark(FuncR(Mat2))

 test replications elapsed relative user.self sys.self user.child sys.child
1 FuncR(Mat2)          100  17.008

    1     7.228    0.016          0         0
库(rbenchmark)

Mat我觉得在5D空间中处理数据帧比处理切片舒服得多,所以下面是我解决这个问题的方法:

library(dplyr)
melt(Mat) %>% 
    setNames(c('i','j','loc','k','Yr','value')) %>% 
    group_by(i,j,loc,Yr) %>% 
    mutate(out=floor(Mat2 %*% value))

当然,也可以使用
data.table
获得类似的解决方案。
dplyr
data.table
解决方案预计比您的代码更快。

我觉得在5D空间中处理数据帧比处理切片舒服得多,因此以下是我解决此问题的方法:

library(dplyr)
melt(Mat) %>% 
    setNames(c('i','j','loc','k','Yr','value')) %>% 
    group_by(i,j,loc,Yr) %>% 
    mutate(out=floor(Mat2 %*% value))

当然,也可以使用
data.table
获得类似的解决方案。
dplyr
data.table
解决方案预计会比您的代码更快。

只需更直接地使用矩阵乘法,您就可以获得与Rcpp类似的性能

使用
aperm
将第四个维度放到前面,然后展平到两个维度。您可以执行一个
%*%
,然后反转该过程

> Mat3 <- aperm(Mat, c(4,1,2,3,5))
> dim(Mat3)
[1]  4 10 10  9  9
> dim(Mat3) <- c(4,prod(10,10,9,9))
> Mat4 <- Mat2 %*% Mat3 
> dim(Mat4)
[1]    4 8100
> dim(Mat4) <- c(4,10,10,9,9)
> Mat5 <- aperm(Mat4, c(2,3,4,1,5))
LGTM

我在“学术”代码中看到过很多这种模式,在行业中则不多见。由于乘法运算已经不存在了,所以它确实用一些内存来弥补代码的不足


如果您对代码库的其他部分有控制,您可以考虑更改<代码> Mat < /Cord>对象的内存布局,然后<>代码> Apple < /C> >不一定需要

< P>。p> 使用
aperm
将第四个维度放到前面,然后展平到两个维度。您可以执行一个
%*%
,然后反转该过程

> Mat3 <- aperm(Mat, c(4,1,2,3,5))
> dim(Mat3)
[1]  4 10 10  9  9
> dim(Mat3) <- c(4,prod(10,10,9,9))
> Mat4 <- Mat2 %*% Mat3 
> dim(Mat4)
[1]    4 8100
> dim(Mat4) <- c(4,10,10,9,9)
> Mat5 <- aperm(Mat4, c(2,3,4,1,5))
LGTM

我在“学术”代码中看到过很多这种模式,在行业中则不多见。由于乘法运算已经不存在了,所以它确实用一些内存来弥补代码的不足


如果您对代码库的其他部分有控制,您可以考虑更改<代码> Mat < /Cord>对象的内存布局,然后<代码> Apple < /C> >将不需要

< P>可选地,您可以考虑<代码>张量库:

> require(tensor)
> MT <- tensor(Mat2, Mat, 2, 4)
> dim(MT)
[1]  4 10 10  9  9
> MT[,1,1,1,1]
[1]  6.357168721 18.288843057 21.215756948 10.310288982
>需要(张量)
>MT dim(MT)
[1]  4 10 10  9  9
>MT[,1,1,1,1]
[1]  6.357168721 18.288843057 21.215756948 10.310288982

< /代码>

可选地,您可以考虑<代码>张量< /C>库:

> require(tensor)
> MT <- tensor(Mat2, Mat, 2, 4)
> dim(MT)
[1]  4 10 10  9  9
> MT[,1,1,1,1]
[1]  6.357168721 18.288843057 21.215756948 10.310288982
>需要(张量)
>MT dim(MT)
[1]  4 10 10  9  9
>MT[,1,1,1,1]
[1]  6.357168721 18.288843057 21.215756948 10.310288982

代码现在的样子——它肯定会从使用Rcpp中受益;我的感觉是,您将获得至少一个数量级的运行时提升。然而,我认为在R中也可能有一种有效的方法,例如,以长格式展开
Mat
,并使用
数据。table
为什么这行中有
assign
<代码>Mat比较(有点普遍),包括Rcpp。代码现在的样子——它肯定会从使用Rcpp中受益;我的感觉是,您将获得至少一个数量级的运行时提升。然而,我认为在R中也可能有一种有效的方法,例如,以长格式展开
Mat
,并使用
数据。table
为什么这行中有
assign
<代码>已比较的材料(有点普遍),包括Rcpp。