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

我想加速下面的R函数。 对于矩阵“A”中的每一列,找出其与向量的另一个元素和对称相关矩阵R中相应元素的乘积最大化的索引(而不是索引本身)

目前,在计算外积时存在一些冗余,因为它不必要地生成完整矩阵。此外,循环(即“应用”)最好是矢量化的

下面是示例数据

    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