Можно ли отделить подцели от цели ветвления Dynami c таким образом, чтобы последующие цели ветвления Dynami c получали только одну подцель? - PullRequest
0 голосов
/ 28 мая 2020

У меня есть план вроде:

plan = drake::drake_plan(

    targ1 = target(
        f1(input)
        , dynamic = map(input)
    )

    , targ2 = target(
        f2(targ1)
        , dynamic = map(targ1)
    )
)

Где функция f1 на самом деле выдает несколько фрагментов вывода (скажем, в списке), и я бы хотел, чтобы эти несколько фрагментов обрабатывались отдельно когда вычисляется targ2. Возможно ли это?

Вот минимальный пример:

f1 = function(x){
    return(list(x,x+1))
}

f2 = function(x){
    return(x*2)
}

input = c(1,99)

plan = drake::drake_plan(
    targ1 = target(
        f1(input)
        , dynamic = map(input)
    )
    , targ2 = target(
        f2(targ1)
        , dynamic = map(targ1)
    )
)
drake::make(
    plan
)

Где, как указано в коде, drake получает ошибку при обработке targ2, потому что список в каждой подцели из targ1 не имеет еще не развалился. Очевидно, я мог бы переписать f2, чтобы перебирать список, но это было сделано для демонстрационных целей, и в моем фактическом варианте использования есть веские причины для того, чтобы просто разделить результаты из targ1.

Я подумал Я решил это с помощью:

f1 = function(x){
    return(list(x,x+1))
}

f2 = function(x){
    return(x*2)
}

input = c(1,99)

plan = drake::drake_plan(
    targ1 = target(
        f1(input)
        , dynamic = map(input)
    )
    , targ2 = target(
        unlist(targ1)
    )
    , targ3 = target(
        f2(targ2)
        , dynamic = map(targ2)
    )
)

Но в моем реальном случае использования каждая подцель занимает много памяти, и вычисление targ2, похоже, требует переноса их всех в память, вызывая блокировку поскольку на моей машине заканчивается память.

Я разработал хак, в котором я сохраняю отдельные элементы списка из каждой подцели в targ1 в файл, а затем выполняю list_files() поиск всех таких файлов в качестве ввода для более позднего мишени, а может есть попроще?

Вот хак, который "работает", но явно не идеален:

library(drake)

f1 = function(x){
    out = list(x,x+1)
    for(i in 1:length(out)){
        a = out[[i]]
        save(a,file=paste0(digest::digest(a),'.rda'))
    }
    return(digest::digest(out))
}

f2 = function(x){
    list.files(pattern='.rda')
}

f3 = function(this_rda){
    load(this_rda)
    return(a)
}

f4 = function(x){
    return(x*2)
}

input = c(1,99)

plan = drake::drake_plan(
    targ1 = target(
        f1(input)
        , dynamic = map(input)
    )
    , targ2 = target(
        f2(targ1)
    )
    , targ3 = target(
        f3(targ2)
        , dynamic = map(targ2)
    )
    , targ4 = target(
        f4(targ3)
        , dynamic = map(targ3)
    )
)
drake::make(plan)
readd(targ4)

1 Ответ

1 голос
/ 28 мая 2020

drake не поддерживает динамическое c ветвление внутри динамических c подцелей, но вы можете комбинировать stati c ветвление с динамическим c ветвлением для достижения чего-то очень похожего.

library(drake)
input_values <- c(1, 99)
plan <- drake_plan(
  targ1 = target(
    f1(input),
    transform = map(input = !!input_values)
  ),
  targ2 = target(
    f2(targ1),
    transform = map(targ1),
    dynamic = map(targ1)
  )
)

drake_plan_source(plan)
#> drake_plan(
#>   targ1_1 = f1(1),
#>   targ1_99 = f1(99),
#>   targ2_targ1_1 = target(
#>     command = f2(targ1_1),
#>     dynamic = map(targ1_1)
#>   ),
#>   targ2_targ1_99 = target(
#>     command = f2(targ1_99),
#>     dynamic = map(targ1_99)
#>   )
#> )

Создано 28.05.2020 с помощью пакета . (v0.3.0)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...