не удалось найти функцию внутри цикла foreach

Я пытаюсь использовать foreach для многоядерных вычислений в R.

A <-function(....) {
    foreach(i=1:10) %dopar% {
    B()
    }
}

затем я вызываю функцию A в консоли. Проблема в том, что я вызываю функцию Posdef внутри B, которая определена в другом файле сценария, источником которого я являюсь. Мне пришлось поместить Posdef в список аргументов экспорта foreach: .export=c("Posdef"). Однако я получаю следующую ошибку:

Error in { : task 3 failed - "could not find function "Posdef""

Почему R не может найти эту определенную функцию?


person statistician_in_training    schedule 22.01.2011    source источник
comment
Я бы рекомендовал поискать информацию о динамической области видимости с помощью R. Это совсем не интуитивно понятно, и вы найдете много вопросов по SO, которые подробно описывают людей, у которых возникают проблемы при определении функции внутри функции.   -  person Brandon Bertelsen    schedule 23.01.2011
comment
Мы были бы признательны за воспроизводимый пример. А еще пробовали ли вы снегопад для мультикоринга? Я считаю, что это более интуитивно понятно и легче адаптируется (изменение функций применения).   -  person Roman Luštrik    schedule 23.01.2011
comment
та же проблема, на данный момент не нашел простого ответа. Мне удалось заставить его работать, вызвав 4 ядра foreach (j = 1: N, .combine = rbind, .packages = c (ВЕКТОР ПАКЕТОВ, НЕОБХОДИМЫЙ ДЛЯ ВЫЗОВА ВСЕХ ВАШИХ ФУНКЦИЙ))% dopar% fun (j). Это улучшает скорость, но не делится на 4 (только на 2). Я не уверен, что делаю, поэтому не повторяйте это ..   -  person RockScience    schedule 10.03.2011
comment
Я решил свою проблему, экспортировав все проблемные функции с clusterExport(cl, 'myMean'), предложенным здесь stackoverflow.com/questions/17879766/   -  person user3226167    schedule 09.01.2020


Ответы (3)


Короткий ответ заключается в том, что это была ошибка параллельных бэкендов, таких как doSNOW, doParallel и doMPI, но с тех пор она была исправлена.

Чуть более длинный ответ заключается в том, что foreach экспортирует функции исполнителям, используя специальную среду «экспорта», а не глобальную среду. Раньше это вызывало проблемы для функций, которые были созданы в глобальной среде, потому что среда «экспорта» не входила в их область действия, хотя теперь они были определены в той же среде «экспорта». Таким образом, они не могли видеть какие-либо другие функции или переменные, определенные в среде «экспорта», например «Posdef» в вашем случае.

Бэкэнды doSNOW, doParallel и doMPI теперь изменяют связанную среду с глобальной на среду «экспорта» для функций, экспортируемых через «.export», и, похоже, решили эти проблемы.

person Steve Weston    schedule 26.07.2013
comment
Я думал, что эта проблема решена, но у меня все еще та же проблема с пакетами _1 _, _ 2_, doParallel v 1.0.14, doSNOW v 1.0.16, запущенными на R v 3.5.0 с RStudio v 1.1.453 - person Nemesi; 06.02.2019

Я могу воспроизвести это для любопытных:

require(doSNOW)
registerDoSNOW(makeCluster(5, type="SOCK"))
getDoParWorkers()
getDoParName()
getDoParVersion()

fib <- function(n) {
  if (n <= 1) { return(1) }
  return(fib(n-1) + fib(n-2))
}

my.matrix <- matrix(runif(2500, 10, 50), nrow=50)

calcLotsaFibs <- function() {
  result <- foreach(row.num=1:nrow(my.matrix), .export=c("fib", "my.matrix")) %dopar% {
    return(Vectorize(fib)(my.matrix[row.num,]))
  }
  return(result)
}

lotsa.fibs <- calcLotsaFibs()

Мне удалось обойти это, поместив функцию в другой файл и загрузив этот файл в тело foreach. Очевидно, вы также можете переместить определение функции в тело самого foreach.

[РЕДАКТИРОВАТЬ - я ранее предполагал, что, возможно, .export не работает должным образом с именами функций, но было исправлено ниже.]

person Paul Eastlund    schedule 11.04.2012
comment
.export может принимать имена функций. Однако это интересный пример, поскольку я считаю, что проблема в том, что ошибка возникает, когда fib выполняет рекурсивный вызов самого себя, поскольку fib не находится в своей собственной области, как я объясняю в своем ответе. - person Steve Weston; 26.07.2013
comment
Вы имеете в виду, что это могло бы сработать, если бы мы обернули пользовательскую функцию в пакет R? - person agenis; 02.09.2015

Быстрое решение проблемы с foreach% dopar% - переустановить эти пакеты:

install.packages("doSNOW")

install.packages("doParallel") 

install.packages("doMPI")

В моем случае это сработало.

person M_D    schedule 21.08.2017