r - 如何在 R 中并行运行 for 循环
问题描述
假设我有一个函数f()
和一个向量d
f <- function(x) dexp(x, 2)
d <- runif(10, 1, 5)
现在我想执行一个 for 循环
dnew <- numeric(length(d))
for (i in seq_along(dnew)){
dnew[i] <- f(d[i])
}
. 我怎样才能并行执行此操作?
解决方案
示例代码在没有 for 循环的情况下更快:
dnew2 <- f(d) # 'f()' and 'd' from question all.equal(dnew, dnew2) # 'dnew' from question [1] TRUE library(microbenchmark) microbenchmark('for loop' = for (i in seq_along(dnew)){ dnew[i] <- f(d[i]) }, 'vectorized' = { dnew2 = f(d) }) Unit: microseconds expr min lq mean median uq max neval for loop 15.639 16.4455 17.66640 17.0045 18.089 43.938 100 vectorized 1.249 1.3140 1.44039 1.3845 1.516 2.424 100
它可以与foreach并行化:
library(foreach) library(doParallel); registerDoParallel(2) dnew3 <- foreach(i=seq_along(dnew), .combine=c) %dopar% { f(d[i]) } all.equal(dnew, dnew3) [1] TRUE
并行化版本较慢,因为并行开销大于收益。
microbenchmark('for loop' = for (i in seq_along(dnew)){ dnew[i] <- f(d[i]) }, 'foreach' = { dnew3 <- foreach(i=seq_along(dnew), .combine=c) %dopar% { f(d[i]) } }) Unit: microseconds expr min lq mean median uq max neval for loop 17.799 22.048 31.01027 32.7615 37.0945 67.265 100 foreach 11875.845 13003.558 13576.64759 13427.1015 14041.3455 17782.638 100
如果
f()
需要更多时间进行评估,则foreach版本更快:f <- function(x){ Sys.sleep(.3) dexp(x, 2) } microbenchmark('for loop' = for (i in seq_along(dnew)){ dnew[i] <- f(d[i]) }, 'foreach' = {dnew3 <- foreach(i=seq_along(dnew), .combine=c) %dopar% { f(d[i]) } }, times=2) Unit: seconds expr min lq mean median uq max neval for loop 3.004271 3.004271 3.004554 3.004554 3.004837 3.004837 2 foreach 1.515458 1.515458 1.515602 1.515602 1.515746 1.515746 2
推荐阅读
- linux - CAN socketCAN - 文件传输的可靠性如何
- python - 如何在 Docker 中安装模块(Selenium、Python)
- scrum - icescrum 具有值的字段 startDate 不遵守自定义验证
- postgresql - 可以从父母那里继承的 Postgres 父子行级安全性?
- symfony - 脚本启动时的 Symfony 5 教义迁移错误
- sql - 比较两个表并使用 SQL Server 过程在第三个表中插入所有具有添加或删除状态的记录
- three.js - 3d-force-graph 和 Three.js - 为单个节点和节点组添加几何发光/大气材质/简单纹理
- ios - 核心数据错误:在范围内没有 NSManagedObjectContext 时无法获取
- excel - 在vba中使用带有多个条件的if语句循环遍历给定范围内的每一行
- json - 如何使用 Azure ARM 模板从 keyvault 传递秘密值