我可以用R{targets}包为不同的目标设置不同的并行度吗



我正在测试targets包,遇到了自定义并行化的问题。我的工作流程有两个步骤,我想将第一个步骤并行到4个工作人员,将第二个步骤并行化到16个工作人员。

我想知道我是否可以通过调用tar_make_future()来解决这个问题,然后在tar_target调用中指定每个步骤需要多少工人。下面有一个简单的例子,我希望data步骤由1个工作人员执行,sums步骤由3个工作人员来执行。

library(targets)
tar_dir({
tar_script({
library(future)
library(future.callr)
library(dplyr)
plan(callr)
list(
# Goal: this step should execute with 1 worker
tar_target(
data,
data.frame(
x = seq_len(6),
id = rep(letters[seq_len(3)], each = 2)
) %>%
group_by(id) %>%
tar_group(),
iteration = "group"
),
# Goal: this step should execute with 3 workers, in parallel
tar_target(
sums,
sum(data$x),
pattern = map(data),
iteration = "vector"
)
)
})
tar_make_future()
})

我知道一个选项是在每个步骤中分别配置并行后端,然后调用tar_make()以串行执行工作流。我很好奇用tar_make_future()是否能得到这样的结果。

我建议您调用tar_make_future(workers = <max_parallel_workers>),让targets计算出并行运行的工作线程数。targets自动计算出哪些目标可以并行运行,哪些需要等待上游依赖关系完成。在您的情况下,一些data分支可能会在其他分支之前完成,在这种情况下,sum可以立即开始。换句话说,一些sum分支将在其他sum分支启动之前开始运行,并且您可以信任targets在需要时扩展临时工作者。上的动画https://books.ropensci.org/targets/hpc.html#future可能有助于将其可视化。如果要分别对datasum的并行性进行微观管理,则可能需要等待所有data完成后,才能启动任何sum,这可能需要很长时间。

适用于我的案例的解决方案是调用tar_make_future()两次。在上面的例子中,这将是:

tar_make_future(data, workers = 1)
tar_make_future(workers = 3)

尽管在我的实际工作流程中,它看起来更像:

tar_make_future(data, workers = 4)
tar_make_future(workers = <max_parallel_workers>)

@landau提出了一个很好的观点,即在进入后续步骤之前,这完全构建了data目标。当然,在某些工作流中,一个干净有效的解决方案是调用tar_make_future(workers = <max_parallel_workers>)并接受生成的运行时。

在我的情况下,等待data完成并不是一个问题:我的data目标包含许多快速的分支,后续目标的构建速度要慢得多,而且我可以在比快速步骤多得多的工作人员上并行执行慢速步骤(慢速步骤有16个以上的工作人员,而快速步骤只有4个(。如果你的情况并非如此,@landau的建议可能是一个更好的解决方案。

最新更新