Шаблон центрального хранилища, с которым работники обращаются за значениями, реализован в пакете rredis в CRAN. Идея состоит в том, что сервер Redis поддерживает хранилище пар ключ-значение (ваш глобальный фрейм данных, повторно реализован). Рабочие опрашивают сервер, чтобы узнать, было ли рассчитано значение (redisGet
), а если нет, то проведите расчет и сохраните его (redisSet
), чтобы другие работники могли использовать его повторно. Рабочие могут быть R-сценариями, поэтому легко расширить рабочую силу. Это очень хорошая альтернативная параллельная парадигма. Вот пример, который использует понятие «запоминания» каждого результата. У нас есть функция, которая работает медленно (спит секунду)
fun <- function(x) { Sys.sleep(1); x }
Мы пишем «памятку», которая возвращает вариант fun
, который сначала проверяет, было ли уже вычислено значение для x
, и если да, то использует
memoize <-
function(FUN)
{
force(FUN) # circumvent lazy evaluation
require(rredis)
redisConnect()
function(x)
{
key <- as.character(x)
val <- redisGet(key)
if (is.null(val)) {
val <- FUN(x)
redisSet(key, val)
}
val
}
}
Затем мы запоминаем нашу функцию
funmem <- memoize(fun)
и иди
> system.time(res <- funmem(10)); res
user system elapsed
0.003 0.000 1.082
[1] 10
> system.time(res <- funmem(10)); res
user system elapsed
0.001 0.001 0.040
[1] 10
Для этого требуется сервер redis, работающий вне R, но очень простой в установке; см. документацию, прилагаемую к пакету rredis.
Параллельная версия в пределах R может быть
library(snow)
cl <- makeCluster(c("localhost","localhost"), type = "SOCK")
clusterEvalQ(cl, { require(rredis); redisConnect() })
tasks <- sample(1:5, 100, TRUE)
system.time(res <- parSapply(cl, tasks, funmem))