一种使数组/矩阵乘法更快的方法?在R

一种使数组/矩阵乘法更快的方法?在R,r,matrix,parallel-processing,R,Matrix,Parallel Processing,我想不出一种方法来加快这段代码的速度。是否有运行速度更快的应用功能?现在,我使用for-each循环来并行运行这个循环,这仍然需要很长的时间 ndraws=20000 nhousehold=18831 m=12 elasticitydraws = array(0,c(m,ndraws,nhousehold)) MAPelasticity = matrix(0,nhousehold,m) medianpricemat = matrix(rnorm(12,15,1),12

我想不出一种方法来加快这段代码的速度。是否有运行速度更快的应用功能?现在,我使用for-each循环来并行运行这个循环,这仍然需要很长的时间

ndraws=20000
nhousehold=18831
m=12


    elasticitydraws = array(0,c(m,ndraws,nhousehold))
    MAPelasticity = matrix(0,nhousehold,m)
    medianpricemat = matrix(rnorm(12,15,1),12,1)                                 


# dim(out$betadraw) = 18831, 12, 20000
# dim(medianpricemat) = 12, 1

    library(foreach)
    library(doMC)
    registerDoMC(10)

    elasticitylist = foreach(i=1:nhousehold) %dopar% {

            pricedraws = out$betadraw[i,12,] 
            elasticitydraws[,,i]= probarray[,,i] %*% diag(pricedraws)
            elasticitydraws[,,i] = elasticitydraws[,,i] * as.vector(medianpricemat)
            MAPelasticity[i,] = apply(elasticitydraws[,,i],1,mean)

    } 

代码中的瓶颈是创建一个大的密集对角矩阵以及与之相乘的矩阵。最好使用稀疏矩阵和
矩阵
包。这节省了内存和计算时间。我还包括了卡尔的评论,并在循环之外创建了一些向量

library(Matrix)

medianpricemat <-  as.vector(medianpricemat)
D1 <- Diagonal(x=pricedraws)

elasticitylist = foreach(i=1:nhousehold) %dopar% {
    pricedraws = out$betadraw[i,12,] 
    tmp = probarray[,,i] %*% D1
    elasticitydraws[,,i] = as.matrix(tmp) * medianpricemat
    MAPelasticity[i,] = rowMeans(elasticitydraws[,,i])
} 
库(矩阵)

MediaNPricmat有两件小事:创建
vecmpThanks Carl,我会解决这个问题。我认为真正缓慢的步骤是第二行和第三行的计算(在循环中)。有没有一种方法可以使用apply或单一类型的整形使其仅为线性alg而不是循环?library(Matrix)是您的朋友。你的问题是矩阵乘法。diag(pricedraws)在每次迭代中构造一个20000*20000密集矩阵。只需使用一个稀疏的对角矩阵,代码的运行速度应该快20000倍左右。foreach循环可能会恶化您的问题,因为您将耗尽内存。我不知道foreach的具体情况,但对于某些框架,每个进程有更大的工作块更有效。您可以尝试调用“foreach(i=seq.int(celliing(nhousehold/10))”,并在每个dopar块中调用“for(i in 10*i+1:10){…}”。这涉及到一点簿记工作,尽管
nhousehold
不是10的倍数,它可能更有效,也可能不更有效,这取决于foreach如何管理并行计算。只是一些尝试…稀疏矩阵的东西实际上使循环非常快!!如果克拉什回答,我会尽力的
D2 <- rep(pricedraws, each=m)

elasticitylist = foreach(i=1:nhousehold) %dopar% {
    pricedraws = out$betadraw[i,12,] 
    tmp = probarray[,,i] * D2  # element wise multiplication 
    elasticitydraws[,,i] = as.matrix(tmp) * medianpricemat
    MAPelasticity[i,] = rowMeans(elasticitydraws[,,i]) 
}