R语言Picante包evol.distinct函数并行运行失败求助
原并行代码的核心错误
- 并行计算时每个工作节点的运行环境相互独立、且和主环境隔离,你在
%dopar%块内修改主环境定义的ed_calc矩阵不会同步回主进程,最终主环境里的ed_calc还是最开始定义的空矩阵。 - 你设置的
combine='rbind'是按行合并结果,但原串行逻辑是每列存一棵树的ED值,合并逻辑和需求完全不匹配。 - 没有在并行环境中显式加载
picante包,工作节点找不到evol.distinct函数会直接抛出报错;后续取行名时调用的newdata是循环内的临时对象,并行结束后主环境不存在这个对象,会报找不到对象的错误。 - 之前设置
n.cores-6只开2个核心,对8核的CPU来说资源浪费比较严重。
修正后可直接运行的代码
# 加载所需依赖 library(picante) library(parallel) library(doParallel) library(foreach) library(matrixStats) # 读入多棵系统发育树 phy <- read.nexus("output.nex") # 提前提取统一的物种名(假设所有树的tip标签完全一致) sorted_species <- sort(phy[[1]]$tip.label) tree_num <- length(phy) # 注册并行集群 core_num <- detectCores() # 留1-2个核心给系统进程即可 cl <- makeCluster(core_num - 2, type = "FORK") registerDoParallel(cl) # 并行计算每棵树的ED值,结果直接按列合并 ed_calc <- foreach( i = 1:tree_num, .combine = "cbind", .packages = "picante" ) %dopar% { ed_result <- evol.distinct(phy[[i]], type = "fair.proportion") # 按物种名排序后返回ED值,保证每一行对应同一物种 ed_result[order(ed_result[,1]), 2] } # 关闭集群,释放资源 stopCluster(cl) # 整理结果格式 ed_calc <- as.data.frame(ed_calc) rownames(ed_calc) <- sorted_species colnames(ed_calc) <- paste0("tree_", 1:tree_num) # 输出所有树的ED计算结果 write.table(ed_calc, file = "ED_Allpar.txt", append = FALSE, quote = TRUE, sep = " ", eol = "\n", na = "NA", dec = ".", row.names = TRUE, col.names = TRUE, qmethod = c("escape", "double"), fileEncoding = "") # 计算每个物种ED的中位数并输出 ed_median <- rowMedians(as.matrix(ed_calc)) write.table(ed_median, file = "ED_Medianpar.txt", append = FALSE, quote = TRUE, sep = " ", eol = "\n", na = "NA", dec = ".", row.names = TRUE, col.names = TRUE, qmethod = c("escape", "double"), fileEncoding = "")
补充说明
- 运行前请确认所有输入的系统发育树包含完全一致的物种标签,否则按名称排序后行对应的物种会出现错位。
- Manjaro系统支持
FORK类型的集群,内存开销更小、启动速度更快;如果后续需要在Windows系统运行,要把集群类型改成PSOCK,同时通过.export参数把需要的对象传到工作节点。 - 如果单棵树的计算量不大,核心数不用开太多,避免多进程调度的开销抵消并行带来的速度提升。
内容的提问来源于stack exchange,提问作者Victor Manuel Martinez Arias
相关产品推荐
相关产品推荐

