是否可以从动态分支目标中拆分子目标,以便以后的动态分支目标仅获得一个子目标?

Is it possible to split subtargets from a dynamic branching target such that later dynamic branching targets get just one subsubtarget?

我有这样的计划:

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
)

根据编码,德雷克在处理 targ2 时出错,因为来自 targ1 的每个子目标中的列表尚未分解。显然我可以重写 f2 来遍历列表,但这是为了演示目的,在我的实际用例中有充分的理由想要简单地从 targ1.[=22= 中拆分结果]

我以为我已经解决了:

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() 搜索所有此类文件作为以后目标的输入,但也许有更简单的方法?

这是 "working" 但肯定不理想的技巧:

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)

drake 不支持动态子目标内的动态分支,但您可以将 static branching 与动态分支结合使用以实现非常相似的效果。

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)
#>   )
#> )

reprex package (v0.3.0)

于 2020-05-28 创建