R语言并行循环在远程桌面运行慢于串行的原因咨询与优化求助
远程R并行运行速度慢的原因
- 代码存在重复集群创建错误:你同时调用了
registerDoParallel(cores=no_cores)和makeCluster(no_cores),前者传入cores参数时会自动创建对应数量的工作进程,后者又手动创建了一次重复的集群,导致资源浪费、调度冲突,额外拉高了系统开销。 - 任务粒度远小于并行开销:你当前测试的单个任务计算量极小,最小的输入n=1时仅需计算1x1矩阵的特征值,运算时间远低于进程间通信、数据序列化反序列化、任务调度的并行 overhead。50个轻量任务分给20核运行时,大部分时间都消耗在通信而非实际计算上。你本地4核设备测试时并行更快,一方面是你本地测试用了更大的n范围(1:70),另一方面本地设备的进程间通信开销本身更低。
- 远程环境的额外限制:如果远程桌面是Windows系统,默认只能使用PSOCK类型的集群,无法使用Linux/Mac支持的fork集群,通信开销会大幅提升;如果20核是超线程得到的逻辑核数,实际物理核数量更少,超线程调度反而会引入额外开销;部分远程桌面环境会对普通用户进程设置CPU、内存带宽配额,也会影响并行效率。
优化方案
- 修正集群注册代码,二选一即可,不要重复创建:
- Linux/Mac环境优先用fork集群,开销最低:
library(rbenchmark) library(foreach) library(doParallel) max.eig <- function(N, sigma) { d <- matrix(rnorm(N**2, sd = sigma), nrow = N) E <- eigen(d)$values abs(E)[[1]] } # 仅填物理核数量,不要用超线程的逻辑核数 no_cores <- 10 registerDoParallel(cores=no_cores) benchmark( foreach(n = 1:50) %do% max.eig(n, 1), foreach(n = 1:50) %dopar% max.eig(n, 1) ) # 运行结束后释放资源 stopImplicitCluster()- 手动创建PSOCK集群的正确写法:
no_cores <- 10 cl <- makeCluster(no_cores) registerDoParallel(cl) # 运行测试代码 stopCluster(cl) - 增大任务粒度:将多个小任务打包为一个大任务再分发,比如把1:50拆分为10组、每组5个n值,单次分发一组任务,大幅降低通信调度的占比。
- 更换更低开销的并行接口:如果任务本身还是偏轻量,可以替换
foreach为parallel包的parLapply,或者用doFuture作为foreach的后端,调度效率比原生doParallel更高。 - 匹配实际业务场景测试:如果你的真实业务场景的单个任务计算量远大于测试用例,直接用真实业务逻辑测试即可,只要单个任务运行时间超过10ms,并行的收益就会超过开销。
内容的提问来源于stack exchange,提问作者Dejan Evisal
相关产品推荐
相关产品推荐

