首页 > 解决方案 > R中具有优先级的异步依赖期货

问题描述

这是一个典型的分析工作流程。

示例分析工作流程

依次运行如下所示:

## some simple functions to mimic longer running models
m1 <- \() {
  Sys.sleep(4*15)
  "model 1 results"
}

m2 <- \() {
  Sys.sleep(3*15)
  "model 2 results"
}

m3 <- \() {
  Sys.sleep(2*15)
  "model 3 results"
}

process <- \(text) {
  Sys.sleep(0.5 * 10)
  sprintf("processed %s", text)
}

###### Approach 1 ~155.2 seconds --- sequential ######
start <- proc.time()

## model 1
m1res <- m1()
p1res <- process(m1res)
cat(p1res, fill = TRUE)

## model 2
m2res <- m2()
p2res <- process(m2res)
cat(p2res, fill = TRUE)

## model 3
m3res <- m3()
p3res <- process(m3res)
cat(p3res, fill = TRUE)

stop <- proc.time()

## total run time
stop - start

大约需要 155.2 秒。使用该future软件包,我们可以加快速度。假设有 2 个 CPU。

###### Approach 2 ~102.7 seconds --- models not blocked but not optimal run ######
## load future package and setup a multisession with 2 workers
library(future)
plan("multisession", workers = 2)


start <- proc.time()

## fit models 
p1res <- future({
  model1 <- m1()
  process(model1)
})
p2res <- future({
  model2 <- m2()
  process(model2)
})
p3res <- future({
  model3 <- m3()
  process(model3)
})

## present results
cat(value(p1res), fill = TRUE)
cat(value(p2res), fill = TRUE)
cat(value(p3res), fill = TRUE)

stop <- proc.time()

## total run time
stop - start

现在我们下降到 ~102.7 秒,但这仍然不是最佳的。理想情况下会发生的是:

###### Approach 3 ~82.7 seconds --- models not blocked but not optimal run ######
start <- proc.time()

## fit models 
m1res %<-% m1()
m2res %<-% m2()
m3res %<-% m3()

## grab results
p1res %<-% process(m1res)
p2res %<-% process(m2res)
p3res %<-% process(m3res)

## present results
cat(p1res, fill = TRUE)
cat(p2res, fill = TRUE)
cat(p3res, fill = TRUE)

stop <- proc.time()

## total run time
stop - start

我们可以得到,现在只需要大约 82.7 秒。但是,代码不再以非常清晰的方式组织。分析 1 的所有内容都不再在一起了。

是否可以像方法 1 那样编写代码,将模型和后处理等放在一起,同时R像第 3 方法一样运行它?伪代码如下所示:


m1res <- future({
  m1()
}, priority = 1)

p1res <- future({
  process(m1res)
}, priority = 2, dependson = "m1res")

m2res <- future({
  m2()
}, priority = 1)

p2res <- future({
  process(m2res)
}, priority = 2, dependson = "m2res")


本质上是某种作业/任务调度程序,可以在未来和优先级列表中构建依赖关系,以便:

(1)任务在可用时贪婪运行,只要依赖关系已经解决(2)如果有多个任务可用,高优先级任务优先于低优先级任务运行。

我尝试使用lazy = TRUE选项future来查看我是否可以将事情排队,但是在使用多会话时,您不能在另一个未来使用未解决的未来。

标签: rpromisefuture

解决方案


推荐阅读