为什么并行 MKL 不比 R 3.6 中的串行快?

Why is MKL in parallel not faster than serial in R 3.6?

我正在尝试将英特尔的 MKL 与 R 一起使用,并使用 MKL_NUM_THREADS 变量调整线程数。

它加载正确,我可以在 htop 中使用 3200% CPU 看到它。但是,它实际上并不比只使用一个线程快。

我一直在为 centos 改编 Dirk Eddelbuettel's guide,但我可能在某处遗漏了一些标志或配置。

这是我如何测试线程数与工作时间的关系的简化版本。使用 OpenBlas 时我确实得到了预期的结果。

require(callr)
#> Loading required package: callr
f <- function(i)  r(function() crossprod(matrix(1:1e9, ncol=1000))[1], 
      env=c(rcmd_safe_env(),
            R_LD_LIBRARY_PATH=MKL_R_LD_LIBRARY_PATH, 
            MKL_NUM_THREADS=as.character(i), 
            OMP_NUM_THREADS="1")
)

system.time(f(1))
#>    user  system elapsed 
#>  14.675   2.945  17.789
system.time(f(4))
#>    user  system elapsed 
#>  54.528   2.920  19.598
system.time(f(8))
#>    user  system elapsed 
#> 115.628   3.181  20.364
system.time(f(32)) 
#>    user  system elapsed 
#> 787.188   7.249  36.388 

reprex package (v0.3.0)

于 2020-05-13 创建

编辑 5/18

根据尝试 MKL_VERBOSE=1 的建议,我现在在 stdout 上看到以下显示正确调用 lapack 的内容:

MKL_VERBOSE Intel(R) MKL 2020.0 Product build 20191122 for Intel(R) 64 architecture Intel(R) Advanced Vector Extensions 512 (Intel(R) AVX-512) with support of Vector Neural Network Instructions enabled processors, Lnx 2.50GHz lp64 intel_thread
MKL_VERBOSE DSYRK(U,T,1000,1000000,0x7fff436222c0,0x7f71024ef040,1000000,0x7fff436222d0,0x7f7101d4d040,1000) 10.64s CNR:OFF Dyn:1 FastMM:1 TID:0  NThr:1

对于 f(8),它显示 NThr:8

MKL_VERBOSE Intel(R) MKL 2020.0 Product build 20191122 for Intel(R) 64 architecture Intel(R) Advanced Vector Extensions 512 (Intel(R) AVX-512) with support of Vector Neural Network Instructions enabled processors, Lnx 2.50GHz lp64 intel_thread
MKL_VERBOSE DSYRK(U,T,1000,1000000,0x7ffe6b39ab40,0x7f4bb52eb040,1000000,0x7ffe6b39ab50,0x7f4bb4b49040,1000) 11.98s CNR:OFF Dyn:1 FastMM:1 TID:0  NThr:8

我仍然没有从额外的内核中获得任何预期的性能提升。


编辑 2

我可以使用 Microsoft 的 MKL 发行版获得预期的结果,但不能像演练中那样使用 Intel 的官方发行版。看来 MS 使用的是 GNU 线程库;问题可能出在线程库中而不是 blas/lapack 本身吗?

我不确定 R 究竟如何调用 MKL,但如果 crossprod 函数调用下面的 mkl 的 gemm,那么我们必须看到使用此类输入的非常好的可伸缩性结果。输入问题的大小是多少? MKL 支持详细模式。当 dgemm 为 运行 时,此选项可以帮助查看许多有用的运行时信息。您可以尝试导出 MKL_VERBOSE=1 环境并查看日志文件吗? 不过,我不太确定 R 是否会抑制输出。

现在才看到这个:您是否检查了明显的一个,即 CentOS 上的 R 是否真的选择了 MKL?

我记得,CentOS 上的 R 是在更多,咳咳,"restricted" 模式下构建的,带有附带的 R 参考 BLAS。如果是这种情况,您 根本无法 切换并选择另一个,就像我们在 Debian 和 Ubuntu 中所做的那样 20 多年,因为这需要不同的初始选择R已编译。

编辑: 根据后续讨论(请参阅下面的评论),我们都重新意识到对齐线程库/模型很重要。 MKL 是 Intel 产品,默认使用他们的线程库,在 Linux 上,GNU 编译器更接近系统并且有自己的。需要选择后一个。在我的 writeup / script for the MKL on .deb systems 中,我使用

echo "MKL_THREADING_LAYER=GNU" >> /etc/environment 

所以在机器上设置这个"system-wide",也可以只将它添加到R环境文件中。