为什么我的工作人员在使用bigmatrix并只发送描述符的情况下还要花这么长时间才能开始我的大矩阵乘法?
我想实现操作的并行版本为什么我的工作人员在使用bigmatrix并只发送描述符的情况下还要花这么长时间才能开始我的大矩阵乘法?,r,matrix,parallel-processing,r-bigmemory,R,Matrix,Parallel Processing,R Bigmemory,我想实现操作的并行版本M%*%t(M)。我有一台有100个内核和共享内存/硬盘的机器,我希望尽可能高效地使用它 因为我的矩阵相当大(20000x15000),所以我希望避免拆分矩阵并直接将块发送给工人,因为这是连续发生的 相反,通过使用bigmemory包,我只能将矩阵描述符和行索引发送给我的工作人员。这是一个很小的数据,所以每个工人都应该很快得到“简报”。然后,每个worker将并行地连接共享内存中的矩阵。输出矩阵也是如此,每个worker并行写入(当然,每个都写入不同的行) 然而,问题是,工
M%*%t(M)
。我有一台有100个内核和共享内存/硬盘的机器,我希望尽可能高效地使用它
因为我的矩阵相当大(20000x15000),所以我希望避免拆分矩阵并直接将块发送给工人,因为这是连续发生的
相反,通过使用bigmemory
包,我只能将矩阵描述符和行索引发送给我的工作人员。这是一个很小的数据,所以每个工人都应该很快得到“简报”。然后,每个worker将并行地连接共享内存中的矩阵。输出矩阵也是如此,每个worker并行写入(当然,每个都写入不同的行)
然而,问题是,工人开始工作仍然需要相当长的时间,这导致了我无法使用所有工人的情况,因为第一个工人是在最后一个工人开始工作时完成的。下面是htop的屏幕截图,您可以在其中看到情况
而且,直到下一个工人开始工作所需的时间越长,输入矩阵就越大。我不明白。如下所示,我并行执行的函数mult
得到一个2的整数向量(第一行/最后一行)和由bigmemory::descripe
创建的两个对象;这些对象不依赖于输入矩阵的大小。为什么工人需要更长的时间来开始更大的矩阵
htop
的屏幕截图:
MCVE
matOuter
定义如下。执行:
mkmatrix <- function(n)
matrix(sample(x = 10, size = n^2, replace = TRUE), nrow = n, ncol = n)
clu <- parallel::makeCluster(100)
n <- 10000
# n <- 1000 # the workers start faster one after another with a smaller matrix
M <- mkmatrix(n)
p <- matOuter(M, parallel = clu)
stopCluster(clu)
第一个问题:“我有一个100核的集群”是什么意思?。是否只有一台计算机有数据?是的;所有内核都可以访问相同的硬盘和内存;问题已编辑。试着运行
cmd,我试过了,得到的值是60。唉,老实说,使用clu,我不知道这个具体问题的答案。然而,我可以告诉你的是,我已经尝试过并行化矩阵运算,每次,最简单、最快的解决方案就是使用一个优化的数学库,比如MKL。
matOuter <- function(M, parallel = 1){
if(is.numeric(parallel)){
# Make a new cluster
if(parallel == 1) return( M %*% t(M))
parallel = parallel::makeCluster(parallel)
on.exit(parallel::stopCluster(parallel))
} # else use the provided cluster.
# Get row index ranges for each worker to tackle
x <- ceiling(seq(1, nrow(M)+1, length.out = min(nrow(M), length(parallel)) + 1))
idxFrom <- x[-length(x)]
idxTo <- x[-1] - 1
idx <- cbind(idxFrom, idxTo)
bM <- bigmemory::as.big.matrix(M, type = "double") # bigalgebra::%*% needs type double (see bigalgebra:::check_matrix)
bMOut <- bigmemory::big.matrix(nrow(M), nrow(M), dimnames = rownames(M))
mult <- function(row, descIn, descOut){
library(bigalgebra)
A <- bigmemory::attach.big.matrix(descIn)
O <- bigmemory::attach.big.matrix(descOut)
O[row[1]:row[2], ] <- t(bigmemory::as.matrix(A %*% t(A[row[1]:row[2],,drop = FALSE])))
return(NULL)
}
dM <- bigmemory::describe(bM)
dO <- bigmemory::describe(bMOut)
# Serial version for debugging.
#apply(idx, 1, mult, descIn = dM, descOut = dO)
parallel::parApply(parallel, idx, 1, descIn = dM, descOut = dO, FUN = mult)
return(bigmemory::as.matrix(bMOut))
}
R version 3.4.3 (2017-11-30)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: CentOS Linux 7 (Core)
Matrix products: default
BLAS: /opt/Bio/R/3.4.3/lib64/R/lib/libRblas.so
LAPACK: /opt/Bio/R/3.4.3/lib64/R/lib/libRlapack.so
locale:
[1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
[3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
[5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
[7] LC_PAPER=en_US.UTF-8 LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] prAtm_0.0
loaded via a namespace (and not attached):
[1] Rcpp_0.12.17 roxygen2_6.0.1 digest_0.6.15
[4] withr_2.1.1 commonmark_1.4 R6_2.2.2
[7] magrittr_1.5 bigmemory.sri_0.1.3 rlang_0.1.6
[10] stringi_1.1.6 testthat_2.0.0 xml2_1.2.0
[13] bigmemory_4.5.33 devtools_1.13.4 tools_3.4.3
[16] stringr_1.2.0 parallel_3.4.3 yaml_2.1.16
[19] compiler_3.4.3 memoise_1.1.0