Windows下R调用mclapply报mc.cores>1不支持错误如何解决
报错原因
parallel包内置的mclapply靠系统层面的fork机制实现多进程并行,Windows系统本身不支持fork类型的多进程,所以只要在Windows环境下给mclapply设置mc.cores > 1就会触发这个报错,和你使用的R 4.2.0版本没有关系,属于系统兼容性问题。
可选修复方案
方案1:切换为串行运行(零配置,最快跑通)
直接把代码里mclapply的mc.cores参数值改为1即可,此时mclapply会退化为和lapply一致的串行执行逻辑,不需要修改其他业务代码,只是失去多核加速效果,20次迭代的计算量不大,串行也可以顺利跑完。
如果需要兼容Mac/Linux系统的多核能力,可以把参数写成自适应判断的形式,不用来回修改:
# 自动识别系统,Windows下自动用1核,类Unix系统用3核 core_num <- ifelse(.Platform$OS.type == "windows", 1, 3) dists = mclapply(1:20, function(ii){ # 此处原有循环内代码完全不变 printprogress(ii, 20, start.time = start.time) dat1 = darwindat %>% add_blob(c(-150, -25)) dat2 = darwindat %>% add_blob(c(-150 + 2*ii, -25), rotate = (ii / 20) * 90) val1 = dat1 %>% pull(val) val2 = dat2 %>% pull(val) costm = form_cost_matrix(dat1) res = omd(M1_long = dat1, M2_long = dat2, p = 1, geodesic = TRUE) diffval = val1 - val2 twodists = c(omd = res$dist, rmse = sqrt(sum((diffval)^2))) return(twodists) }, mc.cores = core_num)
方案2:替换为Windows兼容的多核并行逻辑(保留加速效果)
如果需要在Windows下也用多核缩短计算时间,可以把fork模式的mclapply换成PSOCK集群模式的parLapply,这个并行模式是跨系统兼容的,修改后的完整代码段如下:
library(parallel) start.time = Sys.time() # 初始化3核的并行集群 cl <- makeCluster(3) # 把循环中用到的自定义函数、全局对象导出到集群节点 clusterExport(cl, varlist = c( "darwindat", "printprogress", "add_blob", "form_cost_matrix", "omd", "start.time" )) # 给每个集群节点加载需要用到的依赖包 clusterEvalQ(cl, { library(tidyverse) # 此处补充你运行代码需要加载的其他项目依赖包 }) dists = parLapply(cl, 1:20, function(ii){ # 此处原有循环内代码完全不变 printprogress(ii, 20, start.time = start.time) dat1 = darwindat %>% add_blob(c(-150, -25)) dat2 = darwindat %>% add_blob(c(-150 + 2*ii, -25), rotate = (ii / 20) * 90) val1 = dat1 %>% pull(val) val2 = dat2 %>% pull(val) costm = form_cost_matrix(dat1) res = omd(M1_long = dat1, M2_long = dat2, p = 1, geodesic = TRUE) diffval = val1 - val2 twodists = c(omd = res$dist, rmse = sqrt(sum((diffval)^2))) return(twodists) }) # 计算完成后关闭集群,释放系统资源 stopCluster(cl)
循环执行完成后,后续的距离矩阵计算、RDS保存代码不需要做任何修改,可以直接运行。
注意事项
- 用方案2如果触发「找不到对象」「找不到函数」类报错,把报错提示里提到的对象/函数名补充到
clusterExport的varlist向量里即可 - 只是验证代码逻辑的话优先选方案1,不需要额外配置,改一个参数就能跑通
内容的提问来源于stack exchange,提问作者oliver
相关产品推荐
相关产品推荐

