R包mlr用多核耗尽内存
R package mlr exhausts memory with multicore
我正在尝试 运行 并行使用 mlr
R 包的可重现示例,为此我找到了使用 parallelStartMulticore
(link) 的解决方案. 运行 项目也有 packrat
。
代码 运行 在工作站和小型服务器上正常运行,但 运行 在具有扭矩批处理系统的 HPC 中 运行 会导致内存耗尽。似乎 R 线程是无限产生的,与常规 linux 机器相反。我尝试切换到 parallelStartSocket
,效果很好,但我无法使用 RNG 种子重现结果。
这是一个最小的例子:
library(mlr)
library(parallelMap)
M <- data.frame(x = runif(1e2), y = as.factor(rnorm(1e2) > 0))
# Example with random forest
parallelStartMulticore(parallel::detectCores())
plyr::l_ply(
seq(100),
function(x) {
message("Iteration number: ", x)
set.seed(1, "L'Ecuyer")
tsk <- makeClassifTask(data = M, target = "y")
num_ps <- makeParamSet(
makeIntegerParam("ntree", lower = 10, upper = 50),
makeIntegerParam("nodesize", lower = 1, upper = 5)
)
ctrl <- makeTuneControlGrid(resolution = 2L, tune.threshold = TRUE)
# define learner
lrn <- makeLearner("classif.randomForest", predict.type = "prob")
rdesc <- makeResampleDesc("CV", iters = 2L, stratify = TRUE)
# Grid search in parallel
res <- tuneParams(
lrn, task = tsk, resampling = rdesc, par.set = num_ps,
measures = list(auc), control = ctrl)
# Fit optimal params
lrn.optim <- setHyperPars(lrn, par.vals = res$x)
m <- train(lrn.optim, tsk)
# Test set
pred_rf <- predict(m, newdata = M)
pred_rf
}
)
parallelStop()
HPC 的硬件是 HP Apollo 6000 System ProLiant XL230a Gen9 服务器 blade 64 位,配备 Intel Xeon E5-2683 处理器。如果问题来自扭矩批处理系统、硬件或上述代码中的任何缺陷,我将忽略。 HPC的sessionInfo()
:
R version 3.4.0 (2017-04-21)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: CentOS Linux 7 (Core)
Matrix products: default
BLAS/LAPACK: /cm/shared/apps/intel/parallel_studio_xe/2017/compilers_and_libraries_2017.0.098/linux/mkl/lib/intel64_lin/libmkl_gf_lp64.so
locale:
[1] C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] parallelMap_1.3 mlr_2.11 ParamHelpers_1.10 RLinuxModules_0.2
loaded via a namespace (and not attached):
[1] Rcpp_0.12.14 splines_3.4.0 munsell_0.4.3
[4] colorspace_1.3-2 lattice_0.20-35 rlang_0.1.1
[7] plyr_1.8.4 tools_3.4.0 parallel_3.4.0
[10] grid_3.4.0 packrat_0.4.8-1 checkmate_1.8.2
[13] data.table_1.10.4 gtable_0.2.0 randomForest_4.6-12
[16] survival_2.41-3 lazyeval_0.2.0 tibble_1.3.1
[19] Matrix_1.2-12 ggplot2_2.2.1 stringi_1.1.5
[22] compiler_3.4.0 BBmisc_1.11 scales_0.4.1
[25] backports_1.0.5
"multicore" parallelMap 后端使用 parallel::mcmapply
, 应该 为 [=14= 中的每个评估创建一个新的 fork()
ed 子进程] 然后快速杀死那个进程。根据您用来计算内存使用情况/活动进程的内容,可能会误报内存并显示已经死亡(并且仅存活几分之一秒)的子进程,或者杀死已完成的进程由于某种原因,进程没有发生。
可能出现的问题:
批处理系统无法正确跟踪内存使用情况,无法单独计算每个子进程的父进程内存。 /usr/bin/free
是否实际报告 30GB 已 消失 而脚本是 运行?作为一个更简单的测试用例,考虑 (运行 in an empty R session)
xxx <- 1:1e9
parallel::mclapply(1:4, function(x) {
Sys.sleep(60)
}, mc.cores = 4)
这应该使用大约 4 GB 的内存。如果,在子进程的60秒内,报告的内存使用量是16GB左右,就是这个问题。
内存报告是准确的,但由于某些原因,内存 space 在子进程中发生了很大变化(触发许多 COW 写入),例如因为垃圾收集。在 tuneParams()
调用之前调用 gc()
有帮助吗?
机器上的某些设置阻止 "parallel" 程序包终止子进程。以下:
parallel::mclapply(1:4, function(x) {
xxx <<- 1:1e9 ; NULL
}, mc.cores = 4)
Sys.sleep(60)
应该会占用大约 16 GB 的内存,但请立即释放。如果内存在 Sys.sleep
(以及剩余的 R 会话)期间仍然被使用,则可能是这个问题。
我正在尝试 运行 并行使用 mlr
R 包的可重现示例,为此我找到了使用 parallelStartMulticore
(link) 的解决方案. 运行 项目也有 packrat
。
代码 运行 在工作站和小型服务器上正常运行,但 运行 在具有扭矩批处理系统的 HPC 中 运行 会导致内存耗尽。似乎 R 线程是无限产生的,与常规 linux 机器相反。我尝试切换到 parallelStartSocket
,效果很好,但我无法使用 RNG 种子重现结果。
这是一个最小的例子:
library(mlr)
library(parallelMap)
M <- data.frame(x = runif(1e2), y = as.factor(rnorm(1e2) > 0))
# Example with random forest
parallelStartMulticore(parallel::detectCores())
plyr::l_ply(
seq(100),
function(x) {
message("Iteration number: ", x)
set.seed(1, "L'Ecuyer")
tsk <- makeClassifTask(data = M, target = "y")
num_ps <- makeParamSet(
makeIntegerParam("ntree", lower = 10, upper = 50),
makeIntegerParam("nodesize", lower = 1, upper = 5)
)
ctrl <- makeTuneControlGrid(resolution = 2L, tune.threshold = TRUE)
# define learner
lrn <- makeLearner("classif.randomForest", predict.type = "prob")
rdesc <- makeResampleDesc("CV", iters = 2L, stratify = TRUE)
# Grid search in parallel
res <- tuneParams(
lrn, task = tsk, resampling = rdesc, par.set = num_ps,
measures = list(auc), control = ctrl)
# Fit optimal params
lrn.optim <- setHyperPars(lrn, par.vals = res$x)
m <- train(lrn.optim, tsk)
# Test set
pred_rf <- predict(m, newdata = M)
pred_rf
}
)
parallelStop()
HPC 的硬件是 HP Apollo 6000 System ProLiant XL230a Gen9 服务器 blade 64 位,配备 Intel Xeon E5-2683 处理器。如果问题来自扭矩批处理系统、硬件或上述代码中的任何缺陷,我将忽略。 HPC的sessionInfo()
:
R version 3.4.0 (2017-04-21)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: CentOS Linux 7 (Core)
Matrix products: default
BLAS/LAPACK: /cm/shared/apps/intel/parallel_studio_xe/2017/compilers_and_libraries_2017.0.098/linux/mkl/lib/intel64_lin/libmkl_gf_lp64.so
locale:
[1] C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] parallelMap_1.3 mlr_2.11 ParamHelpers_1.10 RLinuxModules_0.2
loaded via a namespace (and not attached):
[1] Rcpp_0.12.14 splines_3.4.0 munsell_0.4.3
[4] colorspace_1.3-2 lattice_0.20-35 rlang_0.1.1
[7] plyr_1.8.4 tools_3.4.0 parallel_3.4.0
[10] grid_3.4.0 packrat_0.4.8-1 checkmate_1.8.2
[13] data.table_1.10.4 gtable_0.2.0 randomForest_4.6-12
[16] survival_2.41-3 lazyeval_0.2.0 tibble_1.3.1
[19] Matrix_1.2-12 ggplot2_2.2.1 stringi_1.1.5
[22] compiler_3.4.0 BBmisc_1.11 scales_0.4.1
[25] backports_1.0.5
"multicore" parallelMap 后端使用 parallel::mcmapply
, 应该 为 [=14= 中的每个评估创建一个新的 fork()
ed 子进程] 然后快速杀死那个进程。根据您用来计算内存使用情况/活动进程的内容,可能会误报内存并显示已经死亡(并且仅存活几分之一秒)的子进程,或者杀死已完成的进程由于某种原因,进程没有发生。
可能出现的问题:
批处理系统无法正确跟踪内存使用情况,无法单独计算每个子进程的父进程内存。
/usr/bin/free
是否实际报告 30GB 已 消失 而脚本是 运行?作为一个更简单的测试用例,考虑 (运行 in an empty R session)xxx <- 1:1e9 parallel::mclapply(1:4, function(x) { Sys.sleep(60) }, mc.cores = 4)
这应该使用大约 4 GB 的内存。如果,在子进程的60秒内,报告的内存使用量是16GB左右,就是这个问题。
内存报告是准确的,但由于某些原因,内存 space 在子进程中发生了很大变化(触发许多 COW 写入),例如因为垃圾收集。在
tuneParams()
调用之前调用gc()
有帮助吗?机器上的某些设置阻止 "parallel" 程序包终止子进程。以下:
parallel::mclapply(1:4, function(x) { xxx <<- 1:1e9 ; NULL }, mc.cores = 4) Sys.sleep(60)
应该会占用大约 16 GB 的内存,但请立即释放。如果内存在
Sys.sleep
(以及剩余的 R 会话)期间仍然被使用,则可能是这个问题。