ixxmu / mp_duty

抓取网络文章到github issues保存
https://archives.duty-machine.now.sh/
118 stars 30 forks source link

理解并行计算:r future为什么会启动比workers多得多的线程? #2124

Closed ixxmu closed 2 years ago

ixxmu commented 2 years ago

https://mp.weixin.qq.com/s/hG5IVegXw4vJN1UjkUo-OA

github-actions[bot] commented 2 years ago

理解并行计算:r future为什么会启动比workers多得多的线程? by 优雅R

r的future包提供了一种实现多线程并行计算的接口,但有时候在使用时,我发现r启动了比我设定的多得多的计算资源。

简单举一个例子:

data = data.table(
v1 = rnorm(1e8),
v2 = sample(LETTERS, size = 1e8, replace = TRUE)
)

library(future.apply)
plan(multisession, workers = 10)
rv = future_lapply(split(data, data$v2), function(x) {

data.table(
mean = mean(x$v1),
sd = sd(x$v1)
)
})
rv

上面我启用了10个线程(workers)对数据进行处理,但实际运行的时候CPU的资源图可以会类似下面这样:

有时候计算很密集的话,系统的全部CPU都会被占满。

在很久之前我就问过future包的作者,讨论在:https://github.com/HenrikBengtsson/future/issues/343

R语言大神任坤做了一段非常好的解释:

理解起来就是:

  1. 首先问题不是出在future上面,它只是一个管理器之类的东西,启动并行资源最后收集结果。

  2. 问题的核心在于R很多包或者底层库在你不知道的情况下启动了并行计算,例如data.table。举一个例子就是,如果你指定了4个worker,你只想使用4个CPU核心计算,但如果并行计算的内容函数使用了像data.table包的操作,而默认情况下data.table为了加速计算会使用系统全部的核心数目(假设一共20)。也就是你启动的每一个并行计算内容下都会使用全部的CPU核心数运算(4x20 >> 20),自然系统的资源都被占满了。

如@mxblsdl展示的例子,就可以手动进行设定解决这样的问题,即并行计算的函数开头设定仅只使用单线程(这样就变成了 4x1 = 4)。



ixxmu commented 2 years ago

future 在多线程的使用上会遇到很多问题,当然这不是future的问题,因为很多函数自动执行就会调用future的多线程,以后可能要详细说说