大家好!我最近开始使用R编程。我的代码工作正常,但就速度而言,其中一些代码耗时太长而无法正常使用。我希望有人可以帮助我通过优化代码或使用其中一个多核软件包来使代码运行得更快。
我有大型数据集,每个数据集包含大约15000个数字数据。该代码采用两个参数(p,n),其中p> = n,并且生成数据的子集。它将zyp.yuepilon函数(来自zyp包)应用于子集的每一行。然后,参数n用于在n大小的子集上应用相同的函数。
问题是我在嵌套for循环中运行此代码:p在10:40和n在10:40所以它需要一个永恒才能得到结果,而且它只是一个数据集中的许多其他数据集。
sp <- function(p, n){
library(zyp)
data <- runif(15000, 1, 4)
lower <- seq(80 - p + 1, by=1, length.out=length(data)-81)
upper <- lower + p - 1
subsets <- matrix(nrow=length(lower), ncol=p)
for(j in 1:length(lower)){
subsets[j, ] = data[lower[j] : upper[j]]
}
ret <- apply(subsets, 1, zyp.yuepilon)
subset_n <- subsets[, 1:n]
ret2 <- apply(subset_n, 1, zyp.yuepilon)
return(list(ret, ret2))
}
以秒为单位的基准测试结果:
expr min lq median uq max neval
sp(7, 6) 92.77266 94.24901 94.53346 95.10363 95.64914 10
答案 0 :(得分:1)
这是一系列评论,而不是答案。
查看zyp.yuepilon
函数体,通过在R会话中调用不带括号的函数,可以看到此函数和函数zyp.sen
是用纯R代码编写的(而不是编译的)码)。
最大的加速可能是通过使用Rcpp
包来实现的,这有助于在R中调用(编译的)C ++代码。事实上,这里有一个小的线性模型示例Fast LM model using Rcpp/RcppArmadillo。
我倾向于使用zyp.yuepilon
在C ++中重写两个函数zyp.sen
和Rcpp
,包括子集向量的循环(您当前使用的apply
做)。
对于一般的R加速问题,请参阅此问题R loop performance以及R包plyr
,它可能为您的问题采用map-reduce方法提供入口点。
如果你想避开C ++,那么一系列的微观优化将是你最快的胜利。要加快代码的apply
方面,您可以使用类似这样的内容
library(doParallel)
library(parallel)
library(foreach)
library(zyp)
cl<-makeCluster(4)
registerDoParallel(cl)
sp_1<-function(p=7, n=6){
N_ob=15000;
off_set=81;
N_ob_o=N_ob-off_set;
am<-matrix(runif(N_ob*p),ncol=p);
subsets<-am[-(1:off_set),];
ret=matrix(unlist( foreach(i=1:N_ob_o) %dopar% zyp::zyp.yuepilon(subsets[i,]),use.names=FALSE),ncol=11, byrow=TRUE);
subset_n <- subsets[, 1:n]
ret2=matrix(unlist( foreach(i=1:N_ob_o) %dopar% zyp::zyp.yuepilon(subset_n[i,]),use.names=FALSE),nrow=11);
return(list(ret, ret2))
}
sp<-function(p=7, n=6){
data <- runif(15000, 1, 4)
lower <- seq(80 - p + 1, by=1, length.out=length(data)-81)
upper <- lower + p - 1
subsets <- matrix(nrow=length(lower), ncol=p)
for(j in 1:length(lower)){
subsets[j, ] = data[lower[j] : upper[j]]
}
ret <- apply(subsets, 1, zyp.yuepilon)
subset_n <- subsets[, 1:n]
ret2 <- apply(subset_n, 1, zyp.yuepilon)
return(list(ret, ret2))
}
system.time(sp_1())
system.time(sp())
这使我的速度提高了大约2倍。但这取决于您的平台等。查看上面功能和包的帮助文件,并使用{{1}调整群集数量查看哪种方法最适合您的平台(在没有任何关于您的特定设置的信息的情况下)。
另一种方法可能是通过makeCluster
利用字节码编译器来查看是否可以通过这种方式优化各种函数。
library(compiler)