一种使数组/矩阵乘法更快的方法?在R
我想不出一种方法来加快这段代码的速度。是否有运行速度更快的应用功能?现在,我使用for-each循环来并行运行这个循环,这仍然需要很长的时间一种使数组/矩阵乘法更快的方法?在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
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])
}