Почему мои работники так долго не начинают мое большое матричное умножение, несмотря на использование bigmatrix и отправку только дескриптора? - PullRequest
0 голосов
/ 08 июня 2018

Я хочу реализовать распараллеленную версию операции M %*% t(M).У меня есть машина со 100 ядрами и общей памятью / жестким диском, которую я хочу использовать максимально эффективно.

Поскольку моя матрица довольно большая (20000x15000), я хочу не разбивать матрицу и не посылать фрагменты работникам напрямую, потому что это происходит последовательно.

Вместо этого, используя пакет bigmemory, я могу отправлять только дескриптор матрицы и индексы строк моим работникам.Это небольшие данные, поэтому каждый работник должен быть быстро проинформирован.Затем каждый работник прикрепляет матрицу, находящуюся в общей памяти, параллельно.То же самое относится и к выходной матрице, где каждый рабочий пишет параллельно (конечно, в разные строки)

Проблема, однако, в том, что работникам все еще требуется довольно много времени, чтобы начать работать, что приводитв ситуации, когда я не могу использовать всех работников, потому что первые делаются, когда начинаются последние работники.Ниже приведен скриншот htop, на котором вы можете увидеть ситуацию.

Кроме того, продолжительность, с которой следующий рабочий начинает работать, увеличивается, чем больше матрица ввода.Я не понимаю этого.Как вы можете видеть ниже, функция mult, которую я выполняю параллельно, получает целочисленный вектор 2 (первая / последняя строка) и два объекта, созданные bigmemory::describe;эти объекты не зависят от размера входной матрицы.Почему рабочий занимает больше времени, чтобы начать для больших матриц?

Снимок экрана htop:

htop output

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)

Определение функции:

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    
...