如何在purrr中并行运行imap函数?(保留原函数式工具)
用purrr::imap实现聚类重采样的并行运行
问题背景
现有一段基于purrr::imap实现的聚类重采样代码,希望在保持使用imap的前提下实现并行运行,解决参数传递失败的问题。
解决方案
要让imap支持并行,需借助parallel包的集群功能,分系统处理:
1. 通用准备:加载必要包
首先补充加载parallel包:
library(tibble) library(purrr) library(dplyr) library(parallel)
2. Unix/macOS系统(支持fork机制)
直接在imap调用中通过.options指定并行核数即可,无需额外集群配置:
# 生成采样ID(和原代码一致) ids <- unique(df$id) sampled_ids <- sample(ids, length(ids), replace = TRUE) # 重采样函数(和原代码一致) resamp_df <- function(ids, i, data){ df1 <- data[data$id == ids, ] df1$id2 <- rep(i) return(df1) } # 并行调用imap,使用总核数减1(避免占满资源) d1 <- imap(sampled_ids, resamp_df, df, .options = list(parallel = detectCores() - 1)) # 合并结果(和原代码一致) d1 <- bind_rows(d1)
3. Windows系统(需PSOCK集群)
Windows不支持fork,需手动创建并行集群并导出必要对象,确保子进程能访问函数和数据:
# 生成采样ID(和原代码一致) ids <- unique(df$id) sampled_ids <- sample(ids, length(ids), replace = TRUE) # 重采样函数(和原代码一致) resamp_df <- function(ids, i, data){ df1 <- data[data$id == ids, ] df1$id2 <- rep(i) return(df1) } # 创建并行集群,使用总核数减1 cl <- makeCluster(detectCores() - 1) # 导出函数和数据到集群节点(必须步骤,否则子进程找不到对象) clusterExport(cl, c("resamp_df", "df")) # 设置purrr使用该集群 options(purrr.parallel.cluster = cl) # 并行调用imap d1 <- imap(sampled_ids, resamp_df, df, .options = list(parallel = TRUE)) # 合并结果(和原代码一致) d1 <- bind_rows(d1) # 运行结束后关闭集群,释放资源 stopCluster(cl)
关键说明
- Unix/macOS下的并行依赖系统fork机制,无需额外导出对象,配置更简单;
- Windows下必须通过
clusterExport将resamp_df函数和df数据框导出到集群节点,否则子进程无法访问这些对象,导致参数传递失败; - 建议使用
detectCores() - 1指定核数,避免占用全部系统资源。
内容的提问来源于stack exchange,提问作者Ariel Mundo
相关产品推荐
相关产品推荐

