2

我正在尝试使用mlrR 包并行运行一个可重现的示例,为此我找到了使用parallelStartMulticore链接)的解决方案。该项目也运行packrat

代码可以在工作站和小型服务器上正常运行,但在带有扭矩批处理系统的 HPC 中运行会导致内存耗尽。与常规的 linux 机器相反,似乎 R 线程是无限生成的。我尝试切换到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 服务器刀片 64 位,配备 Intel Xeon E5-2683 处理器。如果问题来自扭矩批处理系统、硬件或上述代码中的任何缺陷,我会忽略。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  
4

1 回答 1

4

“多核”parallelMap 后端使用parallel::mcmapply应该fork()为内部的每个评估创建一个新的ed 子进程tuneParams,然后快速终止该进程。根据您用来计算内存使用量/活动进程的方式,可能会误报内存并且显示已经死掉的子进程(并且只存活了几分之一秒),或者杀死完成的进程由于某种原因的过程不会发生。

可能出现的问题:

  • 批处理系统无法正确跟踪内存使用情况,并分别为每个子进程计算父进程的内存。脚本运行时是否/usr/bin/free真的报告 30GB消失了?作为一个更简单的测试用例,考虑(在空的 R 会话中运行)

    xxx <- 1:1e9
    parallel::mclapply(1:4, function(x) {
      Sys.sleep(60)
    }, mc.cores = 4)
    

    这应该使用大约 4 GB 的内存。如果在子进程的 60 秒内,报告的内存使用量大约为 16 GB,就是这个问题。

  • 内存报告是准确的,但由于某些原因,内存空间在子进程内发生了很大变化(触发了许多 COW 写入),例如由于垃圾收集。打电话gc()tuneParams()打电话有用吗?

  • 机器上的某些设置可以防止“并行”包杀死子进程。以下:

    parallel::mclapply(1:4, function(x) {
      xxx <<- 1:1e9 ; NULL
    }, mc.cores = 4)
    Sys.sleep(60)
    

    应该占用大约 16 GB 的内存,但立即释放它。如果内存在Sys.sleep(和剩余的 R 会话)期间仍然使用,则可能是这个问题。

于 2018-01-31T15:57:02.153 回答