Фон
В следующем сценарии я рассматриваю следующий рабочий процесс:
- Функция бегуна верхнего уровня, в примере ниже
running_function
, вызывает несколько меньших функций. - Некоторые из этих функций требуют больших вычислительных ресурсов и будут многократно вызываться для одного и того же набора аргументов, так как функции бегуна, по общему мнению, вызываются сценарием верхнего уровня.
Пример
Если не пытаться кэшировать объекты, ситуацию можно резюмировать следующим образом:
Рабочие функции
painful_function <- function(n = 100) {
matrix(1:n * n, nrow = n)
}
running_function <-
function(stat_to_do = c("min", "max", "mean", "sum"),
painful_size = 1e4) {
stat_to_do <- match.arg(stat_to_do)
M_pain <- painful_function(n = painful_size)
do.call(stat_to_do, list(M_pain))
}
Фактическая работа
# Object M_pain is created inside running_function
running_function(stat_to_do = "min", painful_size = 100)
# I would like to re-use the M_pain object from the previous function
running_function(stat_to_do = "max", painful_size = 100)
# Re-using M_pain again...
running_function(stat_to_do = "mean", painful_size = 100)
# And again ...
running_function(stat_to_do = "sum", painful_size = 100)
Желаемый результат
Идея состоит в том, чтобы не вызывать painful_function
более одного раза, поскольку создаваемый им объект идентичен в каждом из сценариев. Therunning_function
следует оценивать с предоставленными аргументами.
Подход
Я думал об использовании пакета mustashe
:
library("mustashe")
running_function_mstash <-
function(stat_to_do = c("min", "max", "mean", "sum"),
painful_size = 1e4) {
stat_to_do <- match.arg(stat_to_do)
stash(var = "M_pain",
code = {
painful_function(n = painful_size)
},
depends_on = "painful_size")
do.call(stat_to_do, list(M_pain))
}
Это возвращает следующую ошибку:
running_function_mstash(stat_to_do = "min", painful_size = 1e6)
Ошибка в make_hash(depends_on, .TargetEnv): в среде отсутствуют некоторые зависимости.
Вопросы
Мне интересно узнать следующее:
- Как заставить это работать, то есть
running_function
будет выполнятьpainful_function
только в том случае, если один из переданных аргументов изменится, если не полученный объект будет сохранен из файла - Каковы лучшие подходы к использованию этого. Тривиальным методом грубой силы было бы создать временный RDS с причудливым именем и выполнить
painful_function
только в том случае, если файл не существует. Этот хромой подход имеет и очевидные недостатки. Я хотел бы найти надежное решение, которое охватывает аналогичный работоспособный сценарий.
uber_running_function
, который вызывает и сохраняет результатpainful_function
, а затем вызываетrunning_function
по мере необходимости? Все, что вам нужно, это убедиться, чтоrunning_function
может получить этот объект через параметрdata =
. - person Allan Cameron   schedule 27.11.2020