我正在 R Snowfall 包中使用 sfApply 进行并行计算。有 32000 个测试要运行。代码在开始计算时工作正常,它将创建 46 个 Rscript.exe 进程,每个 Rscript.exe 的 cpu 使用率为 2%。总体cpu使用率约为100%,结果不断写入磁盘。计算通常需要数十个小时。奇怪的是,Rscript.exe进程逐渐变得不活跃(cpu使用=0),并且相应的cpu也处于不活跃状态。两天后,通过查看 CPU 使用率,只有一半的 Rscript.exe 处于事件状态,整体 CPU 使用率降低至 50%。然而,这项工作还远远没有完成。随着时间的推移,越来越多的 Rscript.exe 变得不活动,这使得工作持续很长时间。我想知道是什么导致进程和 cpu 核心变得不活动?
我的计算机有 46 个逻辑核心。我在 64 位 Windows 7 中使用 Rstudio 的 R-3.4.0。以下“测试”变量是 32000*2 矩阵。 myfunction 正在求解几个微分方程。
谢谢。
library(snowfall)
sfInit(parallel=TRUE, cpus=46)
Sys.time()
sfLibrary(deSolve)
sfExport("myfunction","test")
res<-sfApply(test,1,function(x){myfunction(x[1],x[2])})
sfStop()
Sys.time()
最佳答案
您所描述的听起来很合理,因为 snowfall::sfApply()
在内部使用 snow::parApply()
,这会将您的数据分块(test
)分成(此处)46 个 block ,并将每个 block 发送给 46 个 R 工作人员之一。当一个工作线程完成它的 block 时,它就不再需要做任何工作,它只会闲置,而其余的 block 则由其他工作线程处理。
你想要做的是将数据分割成更小的 block ,这将导致每个工作人员平均处理多个 block 。我不知道(认为?)降雪是否有可能。并行包是 R 本身的一部分,它取代了 Snow 包(snowfall 所依赖的),提供了 parApply()
和 parApplyLB()
,后者分开了将您的 block 分成最小大小,即每个数据元素(test
)一个。有关详细信息,请参阅 help("parApply", package = "parallel")
。
future.apply包(我是作者),为您提供了缩放数据拆分程度的选项。它不提供 apply()
版本,但提供您可以使用的 lapply()
版本(以及 parApply()
内部工作原理)。例如,每个工作人员使用一个 block 的示例将是:
library(future.apply)
plan(multisession, workers = 46L)
## Coerce matrix into list with one element per matrix row
test_rows <- lapply(seq_len(nrow(test)), FUN = function(row) test[row,])
res <- future_lapply(test_rows, FUN = function(x) {
myfunction(x[1],x[2])
})
默认为
res <- future_lapply(test_rows, FUN = function(x) {
myfunction(x[1],x[2])
}, future.scheduling = 1.0)
如果您想拆分数据,以便每个工作线程一次处理一行(参见 parallel::parApplyLB()
),您可以这样做:
res <- future_lapply(test_rows, FUN = function(x) {
myfunction(x[1],x[2])
}, future.scheduling = Inf)
通过在[1, Inf]中设置future.scheduling
,你可以控制平均 block 大小有多大。例如,在 future_lapply()
返回之前,future.scheduling = 2.0
将使每个工作进程平均拥有两 block 数据。
编辑 2021 年 11 月 8 日:future_lapply()
和 friend 现在位于 future.apply 包中(最初位于 future )。
关于R降雪并行,Rscript.exe随着时间的推移逐渐变得不活跃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44580884/