Пакет R, содержащий foreach, будет работать с doParallel, но не с doMPI, не может найти объект

Я пытаюсь написать пакет R, который содержит несколько вложенных функций в операторе foreach и бэкэнде doMPI. Он выдает ошибку «не могу найти объект «XXX». Странно то, что эта ошибка не возникает, если я использую doParallel в качестве бэкэнда. Это пример проблемы, но я мог бы использовать рабочее решение с doMPI для многих большие проблемы.

Это код, который был скомпилирован в R-Package с помощью RStudio, roxygen, devtools и т. д.

#' Test function level 1
#' @param var11 first variable for function 1
#' @param var12 second variable for function 1
#' @param var13 third variable for function 1
#' @export fun1

fun1 <- function (fun2.params, fun3.params, var11, var12, var13, ...) {

    results <- data.frame (foreach::`%dopar%`(
               foreach::`%:%`(foreach::foreach(j = 1:var11, .combine = cbind),
               foreach::foreach (i = 1:var12, .combine=rbind)),
               {
                   out3 <- replicate(var13,
                                     do.call(fun2,
                                             c(list(fun3.params=fun3.params),
                                               fun2.params)))
                   output2 <- data.frame(mean(out3))
        }
    )
)
    ## save outputs for subsequent analyses if required
saveRDS(results, file = paste("./outputs/", var13 ,"_", var12, "_", var11, "_",
                              format(Sys.time(), "%d_%m_%Y"), ".rds", sep=""))
}

#' Test function level 2
#' @param var21 first variable for function 2
#' @param var22 second variable for function 2
#' @export fun2

fun2 <- function (fun3.params, var21, var22, ...) {
    out2 <- `if` (rpois(1, var21) > 0, var22 * do.call(fun3, fun3.params), 0)
}

#' Test function level 3
#' @param var31 first variable for function 3
#' @param var32 second variable for function 3
#' @param var33 third variable for function 3
#' @export fun3

fun3 <- function (var31, var32, var33, ...) {
    out3 <- var31 * rnorm(1, mean=var32, sd= var33)
}

Затем я загружаю библиотеку и вызываю функцию верхнего уровня из файла .R, используя emacs ESS (или из редактора RStudio), и эти команды

library(toymod)
library(doParallel)
cl <-makeCluster(10)
registerDoParallel(cl)

fun1.params <- list(var11=10, var12=150, var13=365)
fun2.params <- list(var21=0.05,var22=9.876)
fun3.params <- list(var31=1.396,var32=14.387,var33=3.219)

do.call(fun1, c(list(fun2.params = fun2.params,
                     fun3.params = fun3.params),
                fun1.params))

Когда я запускаю его с помощью doParallel в качестве параллельного бэкенда, он работает нормально, однако, когда я запускаю его с помощью doMPI, я получаю следующую ошибку.

Error in { : task 12 failed - "object 'fun2' not found"

Это работает в Ubuntu 16.04 Linux с использованием R 3.4.1, doMPI 0.2.2 и doParallel. Я разместил весь пакет на github по адресу https://github.com/jamaas/toymod.git< /а>

Может ли кто-нибудь сказать мне, нужно ли мне изменить код для doMPI? Кажется, это связано с созданием пакета R.


person Jim Maas    schedule 05.09.2017    source источник
comment
Это предположение, но это может быть связано с тем, что doParallel клонирует вашу родительскую среду R в рабочие процессы X, но doMPI, вероятно, этого не делает. Вам нужно будет экспортировать свои функции из родительской среды в каждый рабочий процесс, cl, или внедрить их в {} из foreach.   -  person CPak    schedule 06.09.2017
comment
Я согласен, что это странно, так как doMPI должен вести себя так же, как doParallel с интерфейсом, производным от snow (что вы и делаете). Я подозреваю, что в doParallel было внесено улучшение/исправление ошибки, чего я никогда не делал в doMPI. Я начинаю разбираться в этом, но это может занять некоторое время.   -  person Steve Weston    schedule 06.09.2017


Ответы (1)


Я считаю, что проблема в том, что вам нужно использовать опцию foreach .packages='toymod'. Это связано с тем, что тело цикла foreach на самом деле не является частью пакета «toymod», и поэтому вам необходимо загрузить «toymod», как и для доступа к функциям из любого другого пакета R.

Я не знаю, почему это не нужно при использовании doParallel. Я предполагаю, что doParallel должен автоматически загружать пакет, в котором находится цикл foreach. Я рассмотрю это еще немного и, возможно, изменю doMPI, чтобы сделать то же самое.

person Steve Weston    schedule 06.09.2017
comment
Это работает! Спасибо. Мне это кажется немного странным, не знаю правильного технического термина, но на ум приходит «круговой» (Уроборос) или «кровосмесительный». Для меня не логично загружать функцию внутри себя, но, возможно, это нормально в некоторых парадигмах программирования? - person Jim Maas; 07.09.2017
comment
@JimMaas Настройка среды для оценки выражения R в удаленных процессах сложна. Вам бы очень хотелось, чтобы тело цикла foreach имело доступ к неэкспортируемым функциям из пакета, в котором оно определено, но я не думаю, что в данных обстоятельствах это возможно. Я думаю, что имеет смысл автоматически загружать пакет, но это по-прежнему рассматривает тело foreach как гражданина второго сорта пакета. - person Steve Weston; 07.09.2017