簡體   English   中英

如何初始化worker並行使用package個函數

[英]How to initialize workers to use package functions in parallel

我正在開發一個 R package 並嘗試在其中使用並行處理來解決一個令人尷尬的並行問題。 我想編寫一個循環或函數,使用我的 package 中的其他函數。我在 Windows 工作,我嘗試使用parallel::parLapplyforeach::%dopar% ,但無法讓工作人員(核心)到訪問我的 package 中的函數。這是一個帶有兩個函數的簡單 package 的示例,其中第二個使用%dopar%在並行循環中調用第一個:

add10 <- function(x) x + 10

slowadd <- function(m) {
  cl <- parallel::makeCluster(parallel::detectCores() - 1)
  doParallel::registerDoParallel(cl)

  `%dopar%` <- foreach::`%dopar%` # so %dopar% doesn't need to be attached

  foreach::foreach(i = 1:m) %dopar% {
    Sys.sleep(1)
    add10(i)
  }

  stopCluster(cl)
}

當我使用devtools::load_all()加載 package 並調用slowadd function 時, Error in {: task 1 failed - "could not find function "add10""被返回。

我還嘗試使用我的 package 顯式初始化工作人員:

add10 <- function(x) x + 10

slowadd <- function(m) {
  cl <- parallel::makeCluster(parallel::detectCores() - 1)
  doParallel::registerDoParallel(cl)

  `%dopar%` <- foreach::`%dopar%` # so %dopar% doesn't need to be attached

  foreach::foreach(i = 1:m, .packages = 'mypackage') %dopar% {
    Sys.sleep(1)
    add10(i)
  }

  stopCluster(cl)
}

但我收到錯誤Error in e$fun(obj, substitute(ex), parent.frame(), e$data): worker initialization failed: there is no package called 'mypackage'

如何讓工作人員訪問我的 package 中的功能? 使用foreach的解決方案會很棒,但我對使用parLapply或其他函數/包的解決方案完全開放。

感謝人們的有用評論,我能夠用我的包的功能初始化工作人員。 通過確保所需的所有 package 函數都在 NAMESPACE 中導出並使用devtools::install()安裝我的 package, foreach能夠找到 package 進行初始化。 該示例的 R 腳本如下所示:

#' @export
add10 <- function(x) x + 10

#' @export
slowadd <- function(m) {
  cl <- parallel::makeCluster(parallel::detectCores() - 1)
  doParallel::registerDoParallel(cl)

  `%dopar%` <- foreach::`%dopar%` # so %dopar% doesn't need to be attached

  out <- foreach::foreach(i = 1:m, .packages = 'mypackage') %dopar% {
    Sys.sleep(1)
    add10(i)
  }

  stopCluster(cl)
  return(out)
} 

這是有效的,但它不是一個理想的解決方案。 首先,它使工作流程慢得多。 每次我對 package 進行更改並想測試它(在合並並行性之前)時,我都在使用devtools::load_all() ),但現在我每次都必須重新安裝 package,當 package 很大時,這很慢。 其次,需要導出並行循環中需要的每個 function,以便foreach可以找到它。 我的實際用例有很多我寧願保留在內部的小實用程序功能。

您可以在 foreach 循環內使用devtools::load_all()或使用source加載您需要的函數。

out <- foreach::foreach(i = 1:m ) %dopar% {
    Sys.sleep(1)
    source("R/some_functions.R")
    load("R/sysdata.rda")
    add10(i)
  }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM