我怀疑该错误与我不了解如何使用 future_pmap 多次运行此函数有关;正如您在下面看到的,我指定 NTrials 来证明我希望该函数在这个特定场景中运行 20 次。如果您希望通过复制代码提供帮助,请注意您正在使用的核心。
library("furrr")
library("parallel")
testmatrix<-matrix(runif((20000*11),-1,21),nrow = 20000, ncol = 11)
Testfunction<-function(ParVp,Ntrials){
for(simnum in 1:Ntrials){
#locate parameters for in-host dynamics
Vp=ParVp[, 1:2]
tp=ParVp[, 3:4]
lg=ParVp[, 5:6]
ld=ParVp[, 7:8]
Tc=ParVp[, 9:10]
rho=ParVp[, 11]
print(head(Vp))
}
}
ncores<-detectCores()-2
plan(multisession, workers = ncores)
Testoutput<- future_pmap(list(testmatrix,20),Testfunction)
plan(sequential)
(function (.l, .f, ..., .progress = FALSE) 中的错误: ℹ 索引:1。 由
ParVp[, 1:2]
中的错误引起:
!维数不正确
您通过
future_*()
进行的函数调用由单个工作人员处理,这意味着您很可能希望避免该函数中中的循环和其他迭代。
从简单开始。
furrr
基本上是 purrr
与 future,因此暂时退出并行性并首先使用 purrr
工作,选择最适合手头任务的 purrr
工具可能是有意义的。
在您的示例中,您有一个矩阵和多个试验,后者可以被视为一系列试验,这将是迭代器的输入。由于我们只需要迭代单个序列,因此这里不需要
pmap()
,只需要 map()
。由于我们(大概)希望获得每次迭代的结果,因此我们的函数也应该返回一些东西。包括 1 秒的延迟,这样我们就可以轻松测量顺序 (purrr
) 和并行 (furrr
) 执行之间的差异。
library(purrr)
set.seed(42)
testmatrix <- matrix(runif((20000*11), -1, 21), nrow = 20000, ncol = 11)
Testfunction <- function(trial_n, ParVp = testmatrix) {
# let's simulate a slowish process, sleep for a ssecond
Sys.sleep(1)
# return something
ParVp[, 1:2] + trial_n * 100
}
n_trials <- 5
# measuring elapsed time
tictoc::tic("map Testfunction")
Testoutput_1 <- map(1:n_trials, Testfunction)
tictoc::toc()
#> map Testfunction: 5.13 sec elapsed
# check results
str(Testoutput_1)
#> List of 5
#> $ : num [1:20000, 1:2] 119 120 105 117 113 ...
#> $ : num [1:20000, 1:2] 219 220 205 217 213 ...
#> $ : num [1:20000, 1:2] 319 320 305 317 313 ...
#> $ : num [1:20000, 1:2] 419 420 405 417 413 ...
#> $ : num [1:20000, 1:2] 519 520 505 517 513 ...
在 5 秒多的时间里,我们获得了输入结果的匹配列表 (
1:n_trials
)。
是时候移动到
furrr
:
library(parallel)
library(furrr)
(ncores <- detectCores() - 2)
#> [1] 6
plan(multisession, workers = ncores)
tictoc::tic("future_map Testfunction")
Testoutput_2 <- future_map(1:n_trials, Testfunction)
tictoc::toc()
#> future_map Testfunction: 2.1 sec elapsed
str(Testoutput_2)
#> List of 5
#> $ : num [1:20000, 1:2] 119 120 105 117 113 ...
#> $ : num [1:20000, 1:2] 219 220 205 217 213 ...
#> $ : num [1:20000, 1:2] 319 320 305 317 313 ...
#> $ : num [1:20000, 1:2] 419 420 405 417 413 ...
#> $ : num [1:20000, 1:2] 519 520 505 517 513 ...
我们在 2.1 秒内获得了 5 次函数调用的结果,每次调用需要 1 秒。
在需要迭代 data.frame 行或确实有超过 2 个列表/向量(对于 2 个有
pmap()
)的情况下,保留 furrr_map()
/ map2
,在后一种情况下,你将向其传递一个列表列表,类似这样的东西?furrr::future_pmap
):
x <- list(1, 10, 100)
y <- list(1, 2, 3)
z <- list(5, 50, 500)
future_pmap(list(x, y, z), my_function_with_3_arguments)
如果你因为“p”像“并行”而选择
pmap
,那么这里的上下文不是“并行执行”,而是并行迭代多个向量,即每次迭代从输入列表中的每个向量中获取第n项。