У меня есть функция doSomething (), которая выполняется в цикле foreach и в результате сохраняет некоторые вычисления в виде файлов .csv. Следовательно, мне не нужно возвращаемое значение foreach, на самом деле я не хочу возвращаемого значения, потому что оно загромождает мою память до такой степени, что я не могу выполнить столько итераций, сколько хотел бы.

Как заставить foreach не иметь возвращаемого значения или удалить возвращаемые значения итераций?

Вот минимальный пример, который иллюстрирует мою проблему:

cl <- parallel::makePSOCKcluster(1)
doParallel::registerDoParallel(cl)

"%dopar%" <- foreach::"%dopar%"

doSomething <- function () {
  a <- as.numeric(1L)
}

foreach::foreach (i = 1:4) %dopar% {

  doSomething()

}

Результат:

[[1]]
[1] 1

[[2]]
[1] 1

[[3]]
[1] 1

[[4]]
[1] 1
5
elmo 5 Фев 2020 в 11:49

3 ответа

Лучший ответ

Параллельные вычисления в R работают (насколько я знаю) так, что для каждого узла кластера будет выделена память.

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

Это работало для E L M, как упоминалось выше. Спасибо за тестирование!

2
Freakazoid 5 Фев 2020 в 12:11

Как отметил Дарио; foreach возвращает список. Следовательно, вместо этого вы должны использовать цикл for. Вы можете использовать функцию write.csv внутри цикла, чтобы записать результаты каждой итерации в файл CSV.

Для параллельных вычислений попробуйте использовать функцию parSapply из пакета parallel:

library(parallel)
cl <- parallel::makePSOCKcluster(1)
doParallel::registerDoParallel(cl)
parSapply(cl, 1:4, function(doSomething) a <- as.numeric(1L))

Редактировать;

Объединяя это с предложением Фрикозоида (установите аргумент функции rm на a);

library(parallel)
cl <- parallel::makePSOCKcluster(1)
doParallel::registerDoParallel(cl)
parSapply(cl, 1:4, function(doSomething) {a <- as.numeric(1L); write.csv(a, "output.csv"); rm()})

Выдаст полученный результат в виде csv-файла, а также список NA с. Поскольку список состоит только из NA s, он может не занимать много места.

Пожалуйста, дайте мне знать результат.

0
Freakazoid 5 Фев 2020 в 14:15

От ?foreach:

Операторы foreach и% do% /% dopar% предоставляют конструкцию цикла, которую можно рассматривать как гибрид стандартной функции for loop и lapply. Он похож на цикл for и оценивает выражение, а не функцию (как в lapply), но его цель - вернуть значение (список по умолчанию), а не вызывать побочные эффекты.

Линия

но его цель - вернуть значение (по умолчанию список)

Говорит, что это предполагаемое поведение foreach. Не уверен, как вы хотите исходить из этого ...

1
dario 5 Фев 2020 в 09:06