如何在R中执行逐元素并行矩阵计算?

时间:2017-09-18 14:59:14

标签: r matrix parallel-processing

我已经看到了一个解决方案,但我正试图找到一种方法,将矩阵分成几个部分,并在一个节点的单独核心上计算每个部分(在Windows和/或Linux中)。

我很欣赏由于延迟等原因,单个矩阵计算可能并行较慢,但我的代码大约有750个矩阵计算,并且对于3000 * 7000矩阵大约需要12秒。

为了使这个可重复,这是一个例子。

假设我有四个矩阵和一个常数:

coln <- 7000
rown <- 3000

t    <- rown * coln

ecells <- matrix(runif(t,0,1),rown,coln)
scells <- matrix(runif(t,0,1),rown,coln)
wcells <- matrix(runif(t,0,1),rown,coln)
ncells <- matrix(runif(t,0,1),rown,coln)

aconstant <- 0.7

然后我计算:

g <- ecells * scells * wcells * ncells *
     ecells * scells * wcells * ncells *
     ecells * scells * wcells * ncells *
     ecells * scells * wcells * ncells *
     aconstant

大约需要1秒钟。

我可以将它放入 Rcpp 犰狳并提高速度:

sourceCpp(code= '#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]

using namespace arma;

// [[Rcpp::export]]
mat moveC( mat ecells, mat scells, mat wcells, mat ncells, double aconstant ) {
  mat result = ecells % scells % wcells % ncells %
               ecells % scells % wcells % ncells %
               ecells % scells % wcells % ncells %
               ecells % scells % wcells % ncells *
               aconstant;
  return result;
}                                   
')
g <- moveC(ecells,scells,wcells,ncells,aconstant)

大约需要0.4秒。

然而,我真正想要做的是将其分布在多个核心并重新组合结果,即将矩阵分开,现在说4个核心(即我的Windows桌面中的核心) - 这需要转移所有必要的数据来执行计算。

最终,当我的矩阵变得足够大时,我想通过MPI做到这一点,但我将把它保存到另一天。

我知道有一些解决方案正在使用Parallel包,可能还有RcppParallelOpenMP,但我似乎只能找到 foreach 类型的例子,我真的不知道如何实现我想要的。

有可能吗?

1 个答案:

答案 0 :(得分:0)

如果你只有4个核心,那就不值得付出努力了,但这就是你如何去做。首先,您需要决定如何将操作拆分为迭代。这就是我决定这样做的方式

g <- ecells * scells * wcells * ncells *    # iteration 1
     ecells * scells * wcells * ncells *    # iteration 2
     ecells * scells * wcells * ncells *    # iteration 3
     ecells * scells * wcells * ncells *    # iteration 4
     aconstant

然后尝试

library(parallel)
cl <- makeCluster(4) # use makeCluster(detectCores()) to be general
clusterExport(cl, c("ecells", "scells", "wcells", "ncells")) # export your variables
parresult <- parLapply(cl, 1:4, function(x) ecells * scells * wcells * ncells) # performs this 4 times

这将导致矩阵的列表(长度4)等于ecells * scells * wcells* ncells*。将它们组合成一个带Reduce的矩阵,并乘以常数

test <- Reduce("*", parresult) * aconstant
stopCluster(cl)

我得到与并行版本相同的结果作为矢量化版本

all.equal(test, g)
[1] TRUE
相关问题