【问题标题】:New hardware running R code slower than old hardware新硬件运行 R 代码比旧硬件慢
【发布时间】:2018-08-14 11:06:48
【问题描述】:

为了测试一个新系统并了解性能,我重新运行了一个 old R project,它有一段用于机器学习的定时代码。

新功能:Ryzen 7 2700X(8 核,16 线程;基本/加速时钟 = 3.7/4.3 GHz),Fedora 28

旧版: Intel i7 4710HQ(4 核,8 线程;基本/加速时钟 = 2.5/3.5 GHz),Windows 7

结果让我震惊——新系统比旧系统慢了 20% 以上

非硬件差异:

  • Windows 7 vs Fedora 28(不知道这是否会影响性能,但this post 报告了显着差异)。默认情况下,Windows 中的 R 是否具有更优化的库?
  • R 的版本(Fedora:来自系统 repo 的 R-3.5.0-4.fc28;Windows:不记得)和使用的软件包不一样,但有 2 年以上的差异,我认为更新的版本和硬件将具有性能优势。

运行 7 或 15 个线程之间的差异仅为约 6%,因此并行化并不能很好地扩展,但我仍然希望更新和更高时钟频率的硬件能够更快地完成(更快)......当然不慢。

这是为什么?


编辑:我用不同数量的线程和 CPB 和 SMT 打开和关闭运行了许多场景。请注意,在某些情况下,系统被轻率地使用,因此应在误差范围内考虑接近的结果。

| user    | system | elapsed  | OS        | CPU       | Threads | Turbo/CPB | HT/SMT | Load average |  
|---------|--------|----------|-----------|-----------|---------|-----------|--------|--------------|  
| 126.421 | 0.532  | 2275.998 | Fedora 28 | R7 2700X  | 8       | ON        | OFF    | >42          |
| 126.583 | 0.541  | 2324.118 | Fedora 28 | R7 2700X  | 7       | ON        | OFF    | ?            |
| 136.636 | 0.574  | 2433.931 | Fedora 28 | R7 2700X  | 7       | OFF       | OFF    | ?            |
| 221.49  | 7.48   | 2679.77  | Windows 7 | i7 4710HQ | 7       | ON        | ON     | ?            |
| 155.427 | 0.555  | 3233.690 | Fedora 28 | R7 2700X  | 15      | ON        | ON     | >100         |
| 168.859 | 0.609  | 3247.277 | Fedora 28 | R7 2700X  | 15      | ON        | ON     | ?            |
| 173.312 | 0.650  | 3250.313 | Fedora 28 | R7 2700X  | 16      | ON        | ON     | >70          |
| 161.403 | 0.611  | 3270.098 | Fedora 28 | R7 2700X  | 14      | ON        | ON     | ?            |
| 162.120 | 0.540  | 3442.758 | Fedora 28 | R7 2700X  | 7       | ON        | ON     | ?            |

总结:线程越多越好,CPB=ON 似乎总是有帮助,但将 SMT=OFF 获得最快的结果。

对负载平均值的偶尔观察表明它们变得非常高,远远大于内核数量。也许上下文切换会影响性能?

【问题讨论】:

  • 不确定延迟或吞吐量,但我认为旧系统具有 DDR3 1600 MHz 或类似的。新系统使用 DDR4 3200 MHz。
  • 负载下的持续频率约为 3.9 GHz。 SMT/HT 已启用。我用 mprime 和 ycruncher 等压力测试测试了这个系统,结果很好。我不介意在禁用“turbo”和“HT”的情况下再次运行我的代码(对于 AMD:核心性能提升 (CPB) 和同时多线程 (SMT))。但从我读过的所有内容来看,这些通常是有帮助的而不是有害的。
  • 你现在使用一些优化的数学库吗?也许你有太多的并行性。我也会按顺序测试它。
  • 抱歉,您在代码中的哪个位置使用了并行性?我看了你的代码,没找到。您只是在注册并行后端。
  • @F.Privé 我正在使用默认的 R 安装,但我不知道这些库可能会实现什么。同样,由于我在旧系统上拥有的唯一数据点是这段代码按原样运行时,那么顺序测试的意义何在?

标签: r performance


【解决方案1】:

由于caret 和一个模型(在本例中为xgboost)都并行化,因此使用更高核心数的 CPU 会降低性能的原因是嵌套并行性。如高负载平均值所示,这会使 CPU 过载,并导致执行时间变慢。

来自caretdocumentation

train、rfe、sbf、bag 和 avNNet 在它们各自的控制文件中被赋予了一个额外的参数,称为 allowParallel,默认为 TRUE。当为 TRUE 时,如果注册了并行后端(例如 doMC),则代码将并行执行。当 allowParallel = FALSE 时,并行后端总是被忽略。用例是当 rfe 或 sbf 调用 train 时。 如果使用具有 P 个处理器的并行后端,这些函数的组合将创建 P^2 个进程。

如果 P 个 CPU 核心有 P^2 个进程,则意味着每个核心都过载了 P 倍。因此,更高核心数的 CPU 实际上可能由于过载更多而性能更差,这似乎是合理的。

解决方案是避免嵌套并行,方法是:

  • 使用模型的并行化而不使用并行后端。这可以通过设置caretallowParallel = FALSE 来完成。

  • 使用并行后端并且不让模型并行化。在xgboost 的情况下,这可以通过设置nthread = 1 来完成。该参数可以在caret::traincaretEnsemble::caretList 中设置,例如。 tuneList=list(xgbLinear=caretModelSpec(method="xgbLinear", nthread=1)).

caret 的作者interesting blog post 帮助展示了每种方法何时更有利:在单个长期运行模型的情况下,前一种解决方案;如果有很多重采样,则后者。因为:

一般来说,我们希望并行化运行时间最长的部分 算法。


使用后一种方法,使用 15 个工作器后端、SMT=ON、CPB=ON、Fedora 28,Ryzen 7 2700X 的整体执行时间显着缩短了约 2.8 倍,达到:

##     user   system  elapsed 
##  109.160    0.638 1168.102

仅训练 xgboost 模型的执行时间(2433 秒或 40.55 分钟是整个执行时间的大部分)减少了约 8 倍至 5 分钟。

【讨论】:

    猜你喜欢
    • 2017-12-25
    • 1970-01-01
    • 1970-01-01
    • 2013-02-15
    • 1970-01-01
    • 2012-05-01
    • 2012-01-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多