R 加速向量乘法
我想加速下面的R函数。 对于矩阵“A”中的每一列,找出其与向量的另一个元素和对称相关矩阵R中相应元素的乘积最大化的索引(而不是索引本身) 目前,在计算外积时存在一些冗余,因为它不必要地生成完整矩阵。此外,循环(即“应用”)最好是矢量化的 下面是示例数据R 加速向量乘法,r,performance,vector,max,multiplication,R,Performance,Vector,Max,Multiplication,我想加速下面的R函数。 对于矩阵“A”中的每一列,找出其与向量的另一个元素和对称相关矩阵R中相应元素的乘积最大化的索引(而不是索引本身) 目前,在计算外积时存在一些冗余,因为它不必要地生成完整矩阵。此外,循环(即“应用”)最好是矢量化的 下面是示例数据 set.seed(123) A <- matrix(rexp(30000, rate=.1), nrow=3000, ncol=2000)/100 R <- matrix( runif(10000), 3000
set.seed(123)
A <- matrix(rexp(30000, rate=.1), nrow=3000, ncol=2000)/100
R <- matrix( runif(10000), 3000 , 3000 )
diag(R) <- 1
R[upper.tri(R)] <- R[lower.tri(R)]
function_which_is_too_slow <- function(index){
aar <- outer(A[,index], A[,index]) * R
diag(aar) <- 0
return(max.col(aar, 'first'))
}
out <- apply(matrix(1:dim(A)[2]), 1, function_which_is_too_slow)
set.seed(123)
A这里您的代码作为基线,问题规模较小:
set.seed(123)
A <- matrix(rexp(30000, rate=.1), nrow=3000, ncol=40)/100
R <- matrix( runif(10000), 3000 , 3000 )
diag(R) <- 1
R[upper.tri(R)] <- R[lower.tri(R)]
function_which_is_too_slow <- function(index){
aar <- outer(A[,index], A[,index]) * R
diag(aar) <- 0
return(max.col(aar, 'first'))
}
system.time(apply(matrix(1:dim(A)[2]), 1, function_which_is_too_slow))
#> User System verstrichen
#> 12.001 11.388 10.348
我们也可以使用RcppArmadillo在C中进行同样的计算++
Rcpp::cppFunction(code = "
arma::uvec arma_function(const arma::mat &A, const arma::mat &Rp, int index) {
arma::mat aar = A.col(index-1) * A.col(index-1).t() % Rp;
return index_max(aar, 1) + 1;
}
", depends ="RcppArmadillo")
system.time(lapply(1:ncol(A), arma_function, A = A, Rp = Rp))
#> User System verstrichen
#> 7.382 10.578 4.874
我们可以并行计算,尽管RcppArmadillo已经使用OpenMP(如果可用):
system.time(parallel::mclapply(1:ncol(A), arma_function, A = A, Rp = Rp))
#> User System verstrichen
#> 0.008 0.010 3.903
总的来说,大约快3倍,这不是很多。我知道它在这里不起作用,但是为了更好的练习,请在使用诸如runif
等函数时使用set.seed
。谢谢,现在可以复制了。apply
不太可能是只有2000列的主要问题。我不确定你是否能用base R做得更好。你的问题描述似乎表明你至少需要看2000*3000*2999/2=90亿个产品。您目前正在寻找2000*3000^2产品,这是2的一个因素,但您正在使用优化的功能,如outer
和max.col
。如果时间是一个问题,那么这似乎是rcpp
system.time(parallel::mclapply(1:ncol(A), arma_function, A = A, Rp = Rp))
#> User System verstrichen
#> 0.008 0.010 3.903