doParallel (): кэширование значений в предопределенной среде [Windows] - PullRequest
0 голосов
/ 28 июня 2018

Я бы хотел больше понять пакет "doParallel". Я играю с окружающей средой. Я хотел бы создать глобальную среду .someEnv<-new.env(parent = emptyenv()) вне foreach() %dopar%{…}

Я знаю, что foreach () должен импортировать все пакеты, функции, значения и данные в функцию foreach(), используя .export= “” и .packages=””.

У меня вопрос: есть ли способы импортировать глобальную среду в foreach(), читать и записывать в эту среду и использовать ее для кэширования вычислений? (пожалуйста, не комментируйте кеширование вычислений с использованием .Rdata, .RDS, .feather и т. д.)

вот пример:

require(doParallel)
library(doSNOW)
getDoParWorkers()
getDoParName()
cl<-makeCluster(4, type = "SOCK")
registerDoSNOW(cl)
getDoParWorkers()
getDoParName()

#define environment
.someEnv<-new.env(parent =  emptyenv())
.someEnv$var<-1:10
.someEnv$squared<-matrix(nrow=10)

#define Function for "foreach"
do.something<-function(x)
{
  .someEnv$squared[x]<-.someEnv$var[x] *.someEnv$var[x]   
   return(.someEnv$squared[x])
}

foreach(i=1:10) %dopar% do.something(i)
stopCluster(cl)

Сообщение об ошибке:

Error in do.something(i) : 
  task 1 failed - "Objekt '.someEnv' nicht gefunden"

1 Ответ

0 голосов
/ 29 июня 2018

Прежде всего, doSNOW и doParallel - это два разных пакета, которые предоставляют бэкэнды для foreach. Вы можете, конечно, проверить оба, только не запутайся. Следующие работы для любого, но ваш вопрос более тесно связан с использованием пакета parallel (который входит в R).

Ваш подход не будет работать, потому что даже если вы поместите свою среду в каждого параллельного работника, это будут копии, которые будут изменены независимо:

foreach(i = 1L:2L) %dopar% {
    .someEnv$hello <- "world"
    .someEnv$hello
}
[[1]]
[1] "world"

[[2]]
[1] "world"

print(.someEnv$hello)
NULL

Однако вы можете использовать пакет bigmemory:

library(doParallel)
library(bigmemory)

cl <- makeCluster(4L)
registerDoParallel(cl)

var <- 1L:10L

squared <- big.matrix(nrow = 10L, ncol = 1L, type = "integer")
# show by coercing to normal matrix
squared[,]
[1] NA NA NA NA NA NA NA NA NA NA

squared_desc <- describe(squared)
# assign it to each worker's global environment
clusterExport(cl, c("squared_desc"))

foreach(i = 1L:10L,
        .noexport = c("squared_desc"),
        .packages = "bigmemory") %dopar%
        {
          squared <- attach.big.matrix(squared_desc)
          squared[i] <- var[i] * var[i]
          NULL
        }

stopCluster(cl); registerDoSEQ()

squared[,]
[1]   1   4   9  16  25  36  49  64  81 100

Обратите внимание, что матрицы из bigmemory строго типизированы внутри, так что если вы определите их как целые числа, Вы должны присвоить им значения, которые являются целыми числами, которые явно указаны в R добавлением L в конце числа, в противном случае вы получите предупреждение об унынии.

Кроме того, вам не нужно принуждать все big.matrix, чтобы использовать его, но почти каждый раз, когда вы получаете доступ к его элементам, вы копируете некоторые данные в обычную матрицу / вектор R.

РЕДАКТИРОВАТЬ: и, наконец, я думаю, что bigmemory не предоставляет никаких механизмов синхронизации для защиты от условий гонки.

...