r的future包提供了一种实现多线程并行计算的接口,但有时候在使用时,我发现r启动了比我设定的多得多的计算资源。
简单举一个例子:
代码语言:javascript复制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语言大神任坤做了一段非常好的解释:
理解起来就是:
- 首先问题不是出在future上面,它只是一个管理器之类的东西,启动并行资源最后收集结果。
- 问题的核心在于R很多包或者底层库在你不知道的情况下启动了并行计算,例如data.table。举一个例子就是,如果你指定了4个worker,你只想使用4个CPU核心计算,但如果并行计算的内容函数使用了像data.table包的操作,而默认情况下data.table为了加速计算会使用系统全部的核心数目(假设一共20)。也就是你启动的每一个并行计算内容下都会使用全部的CPU核心数运算(4x20 >> 20),自然系统的资源都被占满了。
如@mxblsdl展示的例子,就可以手动进行设定解决这样的问题,即并行计算的函数开头设定仅只使用单线程(这样就变成了 4x1 = 4)。