代码之家  ›  专栏  ›  技术社区  ›  F. Privé

矩阵计算操作系统性能差异大

r
  •  5
  • F. Privé  · 技术社区  · 6 年前

    在我的两台电脑上,我尝试了以下代码:

    N <- 10e3
    M <- 2000
    X <- matrix(rnorm(N * M), N)
    system.time(crossprod(X))
    

    第一台是标准笔记本电脑,这个操作需要1.7秒。

    > sessionInfo()
    R version 3.4.4 (2018-03-15)
    Platform: x86_64-redhat-linux-gnu (64-bit)
    Running under: CentOS Linux 7 (Core)
    
    Matrix products: default
    BLAS/LAPACK: /usr/lib64/R/lib/libRblas.so
    

    第二台是相当好的台式电脑,花了17秒。

    > sessionInfo()
    R version 3.4.4 (2018-03-15)
    Platform: x86_64-pc-linux-gnu (64-bit)
    Running under: Linux Mint 18.3
    
    Matrix products: default
    BLAS: /usr/lib/libblas/libblas.so.3.6.0
    LAPACK: /usr/lib/lapack/liblapack.so.3.6.0
    

    台式机比笔记本电脑性能更高,但计算矩阵所需的时间是笔记本电脑的10倍。

    问题是否来自使用的默认blas/lapack?

    2 回复  |  直到 6 年前
        1
  •  7
  •   Ralf Stubner    6 年前

    TLDR: centos使用单线程openblas,linux mint默认使用引用blas,但可以使用其他blas版本。

    epel提供的centos的r包取决于 openblas-Rblas . 这似乎是一个openblas构建,为r提供blas,所以虽然看起来r的blas被使用了,但实际上它是openblas。lapack版本总是r提供的版本。

    在Debian和Mint等衍生发行版上, r-base-core 取决于

    • 利布拉斯3利布拉斯.so.3
    • liblapack3 liblapack.so.3

    默认情况下,这些由引用实现提供 libblas3 liblapack3 . 这些不是特别快,但是您可以通过安装诸如 libopenblas-base . 您可以通过 update-alternatives .

    为了控制openblas的线程数,我通常使用 RhpcBLASctl :

    N <- 20000
    M <- 2000
    X <- matrix(rnorm(N * M), N)
    RhpcBLASctl::blas_set_num_threads(2)
    system.time(crossprod(X))
    #>        User      System verstrichen 
    #>       2.492       0.331       1.339
    RhpcBLASctl::blas_set_num_threads(1)
    system.time(crossprod(X))
    #>        User      System verstrichen 
    #>       2.319       0.052       2.316
    

    出于某种原因设置 environment variables OPENBLAS_NUM_THREADS , GOTO_NUM_THREADS OMP_NUM_THREADS 从r起没有达到预期的效果。甚至在半人马身上 氯化聚乙烯 没有帮助,因为使用的openblas是单线程的。

        2
  •  5
  •   francis    6 年前

    r是使用默认的blas实现来分发的,但可能没有针对您的计算机进行优化。 通过 ATLAS OpenBLAS r之前 as advised on the Installation guide of R 是一条路。如果你坚持下去 Download R for Linux 然后在 debian/ . 据说:

    为了获得更高的线性代数运算性能,您可能需要安装自动调整的atlas或多线程openblas库

    R的来源可以下载 here blas实现位于 R-3.5.0/src/extra/blas . 例如,矩阵乘法的fortran源代码 dgemm 位于blas.f中,以及大多数blas例程(在单个文件中!).

    函数的注释指定:

     -- Written on 8-February-1989.
     Jack Dongarra, Argonne National Laboratory.
     Iain Duff, AERE Harwell.
     Jeremy Du Croz, Numerical Algorithms Group Ltd.
     Sven Hammarling, Numerical Algorithms Group Ltd.
    

    在例程的netlib实现中可以找到相同的行 dgemm .

    相反,openblas提供了不同的实现,每种处理器都有一种实现。例如,请参见 this file devoted to dgemm for haswell microarchitecture . 有人打电话给 prefetcht0 用于预取和调用 vfmadd231pd ,一种向量fma simd指令,一次执行4次双精度d=a*b+c。

    使用优化的blas可以节省时间。例如,请参见 this benchmark ,其中netlib的dgemm()持续64秒,而mkl、openblas或atlas dgemm只需不到4秒。

    r internal blas的情况可能比经典的netlib库更糟。 的确,如附录所述 A.3.1.5 Shared BLAS R Installation and Administration :

    r提供了将blas编译成动态库librblas的选项,该库存储在r_home/lib中,并将r本身和所有附加包与该库相链接。…使用共享blas可能会有性能上的缺点。…然而,实验表明,在许多情况下,只要使用高水平的编译器优化,使用共享blas同样快速。

    查看r的config.site文件,可以发现g77/gfortran的优化级别为'-o2'。因此,如果fortran编译器不是g77/gfortran,那么调整fflags选项可能会证明是有用的。在配置步骤中,应该有一行 checking whether we are using the GNU Fortran 77 compiler... yes (配置文件的第7521行)。