【问题标题】:R: How to use parallelMap (with mlr, xgboost) on linux server? Unexpected performance compared to windowsR: 如何在 linux 服务器上使用 parallelMap (with mlr, xgboost)?与 Windows 相比,性能出乎意料
【发布时间】:2019-09-22 11:49:48
【问题描述】:

我正在尝试在调整超参数级别并行化 xgboost 模型,我正在调整 mlr 并尝试与 parallelMap 并行化。我的代码可以在我的 Windows 机器(只有 8 个内核)上成功运行,并且想使用 linux 服务器(有 72 个内核)。在迁移到服务器时,我无法成功获得任何计算优势,我认为这是由于我对 parallelMap 参数的理解存在漏洞。

我不明白多核与本地与套接字在parallelMap 中作为“模式”的区别。根据我的阅读,我认为多核适用于我的情况,但我不确定。我在我的 windows 机器上成功使用了 socket,并在我的 linux 服务器上尝试了 socket 和 multicore,但结果不成功。

parallelStart(mode="socket", cpu=8, level="mlr.tuneParams")

但据我了解,对于在许多不需要相互通信的内核上进行并行处理,socket 可能是不必要的或者可能很慢,就像并行化超参数调整的情况一样。

详细说明我在我的 linux 服务器上的不成功结果:我没有收到错误,但是串行需要 2 周。查看进程,我可以看到我确实在使用几个内核。

每个单独的调用 xgboost 都会在几分钟内运行,我并不想加快速度。我只是想在几个核心上调整超参数。

我担心我在 linux 服务器上的结果非常缓慢可能是由于 xgboost 尝试利用模型构建中的可用内核,所以我通过 mlr 将 nthread = 1 提供给 xgboost 以确保不会发生这种情况。尽管如此,我的代码在大型 linux 服务器上的运行速度似乎比在较小的 windows 计算机上运行得慢得多——对可能发生的情况有什么想法吗?

非常感谢。

xgb_learner_tune <- makeLearner(
  "classif.xgboost",
  predict.type = "response",
  par.vals = list(
    objective = "binary:logistic",
    eval_metric = "map",
    nthread=1))

library(parallelMap)
parallelStart(mode="multicore", cpu=8, level="mlr.tuneParams")

tuned_params_trim <- tuneParams(
  learner = xgb_learner_tune,
  task = trainTask,
  resampling = resample_desc,
  par.set = xgb_params,
  control = control,
  measures = list(ppv, tpr, tnr, mmce)
)
parallelStop()

编辑

我仍然对尝试在调优级别进行并行化缺乏性能改进感到惊讶。我的期望不公平吗?我使用parallelMap 的性能比在以下过程中串行调优要慢得多:

numeric_ps = makeParamSet(
  makeNumericParam("C", lower = 0.5, upper = 2.0),
  makeNumericParam("sigma", lower = 0.5, upper = 2.0)
)
ctrl = makeTuneControlRandom(maxit=1024L)
rdesc = makeResampleDesc("CV", iters = 3L)

#In serial
start.time.serial <- Sys.time()
res.serial = tuneParams("classif.ksvm", task = iris.task, resampling = rdesc,
                 par.set = numeric_ps, control = ctrl)
stop.time.serial <- Sys.time()
stop.time.serial - start.time.serial

#In parallel with 2 CPUs
start.time.parallel.2 <- Sys.time()
parallelStart(mode="multicore", cpu=2, level="mlr.tuneParams")
res.parallel.2 = tuneParams("classif.ksvm", task = iris.task, resampling = rdesc,
                 par.set = numeric_ps, control = ctrl)
parallelStop()
stop.time.parallel.2 <- Sys.time()
stop.time.parallel.2 - start.time.parallel.2

#In parallel with 16 CPUs
start.time.parallel.16 <- Sys.time()
parallelStart(mode="multicore", cpu=16, level="mlr.tuneParams")
res.parallel.16 = tuneParams("classif.ksvm", task = iris.task, resampling = rdesc,
                          par.set = numeric_ps, control = ctrl)
parallelStop()
stop.time.parallel.16 <- Sys.time()
stop.time.parallel.16 - start.time.parallel.16 

我的控制台输出是(省略调整细节):

> stop.time.serial - start.time.serial
Time difference of 33.0646 secs

> stop.time.parallel - start.time.parallel
Time difference of 2.49616 mins

> stop.time.parallel.16 - start.time.parallel.16
Time difference of 2.533662 mins

我本来希望并行的事情会更快。这个例子不合理吗?如果是这样,我应该在什么时候期望并行提高性能?

查看终端,我似乎正在使用 2(和 16)个线程/进程(如果我的术语不正确,请道歉)。

非常感谢您提供任何进一步的意见。

【问题讨论】:

  • 您是否检查过您的代码是否实际使用了所有 72 个内核?您发布的代码仅使用 8 个内核,因此您不能指望移动到更多内核的加速。听起来这是一台 KNL 机器;请记住,每个内核的时钟速度只是 Windows 计算机时钟速度的一小部分,因此一切都会花费更长的时间。

标签: r parallel-processing mlr


【解决方案1】:

这个问题更多的是猜测你的设置有什么问题,而不是实际提供“真实”的答案。也许您也可以更改标题,因为您没有得到“意外结果”。

几点:

  • nthread = 1 已经是 xgboostmlr 中的默认值
  • multicore 是 UNIX 系统上的首选模式
  • 如果您的本地计算机比您的服务器快,那么您的计算完成得非常快并且两者之间的 CPU 频率有很大不同,或者您应该考虑并行化另一个级别而不是 mlr.tuneParams(有关更多信息,请参阅 here

编辑

我的机器上一切正常。看起来像你这边的本地问题。

library(mlr)
#> Loading required package: ParamHelpers
#> Registered S3 methods overwritten by 'ggplot2':
#>   method         from 
#>   [.quosures     rlang
#>   c.quosures     rlang
#>   print.quosures rlang
library(parallelMap)

numeric_ps = makeParamSet(
  makeNumericParam("C", lower = 0.5, upper = 2.0),
  makeNumericParam("sigma", lower = 0.5, upper = 2.0)
)
ctrl = makeTuneControlRandom(maxit=1024L)
rdesc = makeResampleDesc("CV", iters = 3L)

#In serial
start.time.serial <- Sys.time()
res.serial = tuneParams("classif.ksvm", task = iris.task, resampling = rdesc,
  par.set = numeric_ps, control = ctrl)
#> [Tune] Started tuning learner classif.ksvm for parameter set:
#>          Type len Def   Constr Req Tunable Trafo
#> C     numeric   -   - 0.5 to 2   -    TRUE     -
#> sigma numeric   -   - 0.5 to 2   -    TRUE     -
#> With control class: TuneControlRandom
#> Imputation value: 1
stop.time.serial <- Sys.time()
stop.time.serial - start.time.serial
#> Time difference of 31.28781 secs


#In parallel with 2 CPUs
start.time.parallel.2 <- Sys.time()
parallelStart(mode="multicore", cpu=2, level="mlr.tuneParams")
#> Starting parallelization in mode=multicore with cpus=2.
res.parallel.2 = tuneParams("classif.ksvm", task = iris.task, resampling = rdesc,
  par.set = numeric_ps, control = ctrl)
#> [Tune] Started tuning learner classif.ksvm for parameter set:
#>          Type len Def   Constr Req Tunable Trafo
#> C     numeric   -   - 0.5 to 2   -    TRUE     -
#> sigma numeric   -   - 0.5 to 2   -    TRUE     -
#> With control class: TuneControlRandom
#> Imputation value: 1
#> Mapping in parallel: mode = multicore; level = mlr.tuneParams; cpus = 2; elements = 1024.
#> [Tune] Result: C=1.12; sigma=0.647 : mmce.test.mean=0.0466667
parallelStop()
#> Stopped parallelization. All cleaned up.
stop.time.parallel.2 <- Sys.time()
stop.time.parallel.2 - start.time.parallel.2
#> Time difference of 16.13145 secs


#In parallel with 4 CPUs
start.time.parallel.16 <- Sys.time()
parallelStart(mode="multicore", cpu=4, level="mlr.tuneParams")
#> Starting parallelization in mode=multicore with cpus=4.
res.parallel.16 = tuneParams("classif.ksvm", task = iris.task, resampling = rdesc,
  par.set = numeric_ps, control = ctrl)
#> [Tune] Started tuning learner classif.ksvm for parameter set:
#>          Type len Def   Constr Req Tunable Trafo
#> C     numeric   -   - 0.5 to 2   -    TRUE     -
#> sigma numeric   -   - 0.5 to 2   -    TRUE     -
#> With control class: TuneControlRandom
#> Imputation value: 1
#> Mapping in parallel: mode = multicore; level = mlr.tuneParams; cpus = 4; elements = 1024.
#> [Tune] Result: C=0.564; sigma=0.5 : mmce.test.mean=0.0333333
parallelStop()
#> Stopped parallelization. All cleaned up.
stop.time.parallel.16 <- Sys.time()
stop.time.parallel.16 - start.time.parallel.16 
#> Time difference of 10.14408 secs

reprex package (v0.3.0) 于 2019 年 6 月 14 日创建

【讨论】:

  • 帕特,感谢您的回复。我把标题从意想不到的结果改成了意想不到的表现——这就是你的意思吗?我正在重新审视这个问题,并将用一个非常小的例子来更新我的问题,其中 iris.task 和我系统的性能结果。我发现它们出乎意料——您能否就我是否需要修改我的期望或我的设置提供意见?谢谢!
  • 谢谢。正如您从我的代表中看到的那样,mlr 方面的一切都很好。这一定是你本地机器的问题。
  • 令人着迷。非常感谢你花时间在你的机器上运行它——我一直假设我的实现(代码)有问题,这是次优的。我会将这种性能比较与 IT 进行比较,因为服务器详细信息完全不在我的掌控之中。
  • 你有没有发现是什么导致了你的情况下性能下降?我遇到了同样的问题。在 WIndows 单核机器上调整 XGBoost 学习器在不到一个小时的时间内运行 25 次交互 x 20 种不同的调整设置。当我使用 ParallelMap 在具有 12 个内核的 linux 机器上运行相同的代码时,运行时间很长,以至于我放弃并关闭它(例如 ~36 小时)。这可能是什么原因造成的?所有软件包都是最新的。
  • 我也对结果感兴趣。我遇到了同样的问题:parallelMap 在 Windows 上加快了速度,但在我的 linux ec2 实例上减慢了速度。
猜你喜欢
  • 1970-01-01
  • 2011-07-22
  • 1970-01-01
  • 1970-01-01
  • 2019-03-25
  • 2019-11-05
  • 2020-03-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多