为什么有这么多 OpenBLAS 包,哪一个会产生最快的结果?

Arc*_*ahi 5 apt libraries octave

在Ubuntu 20.04中,有很多OpenBLAS的软件包。

~$ apt search openblas
p   libopenblas-base                              - Optimized BLAS (linear algebra) library (transitional)                                               
p   libopenblas-dev                               - Optimized BLAS (linear algebra) library (dev, meta)                                                  
p   libopenblas-openmp-dev                        - Optimized BLAS (linear algebra) library (dev, openmp)                                                
p   libopenblas-pthread-dev                       - Optimized BLAS (linear algebra) library (dev, pthread)                                               
p   libopenblas-serial-dev                        - Optimized BLAS (linear algebra) library (dev, serial)                                                
i A libopenblas0                                  - Optimized BLAS (linear algebra) library (meta)                                                       
p   libopenblas0-openmp                           - Optimized BLAS (linear algebra) library (shared lib, openmp)                                         
i A libopenblas0-pthread                          - Optimized BLAS (linear algebra) library (shared lib, pthread)                                        
p   libopenblas0-serial                           - Optimized BLAS (linear algebra) library (shared lib, serial)                                         
p   libopenblas64-0                               - Optimized BLAS (linear algebra) library (shared lib, 64bit, meta)                                    
p   libopenblas64-0-openmp                        - Optimized BLAS (linear algebra) library (shared lib, 64bit, openmp)                                  
p   libopenblas64-0-pthread                       - Optimized BLAS (linear algebra) library (shared lib, 64bit, pthread)                                 
p   libopenblas64-0-serial                        - Optimized BLAS (linear algebra) library (shared lib, 64bit, serial)                                  
p   libopenblas64-dev                             - Optimized BLAS (linear algebra) library (dev, 64bit, meta)                                           
p   libopenblas64-openmp-dev                      - Optimized BLAS (linear algebra) library (dev, 64bit, openmp)                                         
p   libopenblas64-pthread-dev                     - Optimized BLAS (linear algebra) library (dev, 64bit, pthread)                                        
p   libopenblas64-serial-dev                      - Optimized BLAS (linear algebra) library (dev, 64bit, serial)
Run Code Online (Sandbox Code Playgroud)

这些包中哪一个会产生最快的结果?

我打算在 GNU Octave 中进行数值计算(主要是对角化矩阵)。我的计算机配备 Intel Core i3-5005U 处理器(如果优化包应取决于处理器类型,请说明在其他类型的处理器上应首选哪个包)。

我注意到,使用 OpenBLAS 而不是默认的 BLAS 时,速度至少提高了 10 倍。

KJ7*_*LNW 7

为什么有这么多?

  • -dev 库包括用于链接的标头和库
  • libopenblas0* 库具有 32 位(即 uint32_t)参数
  • libopenblas64-0* 库具有 64 位(即 uint64_t)参数。
    • 例如zgetrf(),如果您的数组是,uint32_t *ip那么它不适合使用 64 版本,因为您的内存对齐方式是元素之间的 4 字节 ( uint32_t) 而不是 8 字节。您必须重构代码以支持数组元素之间的 8 字节对齐 ( uint64_t)。
    • 如果您使用 64 位但设置为 32 位,则会超出范围崩溃。
    • 如果您使用 32 并设置为 64,它可能不会超出范围,但您不会得到正确的结果。

基准测试

我正在将 LAPACK、ATLAS 和 OpenBLAS 支持集成到xnec2c EM 模拟器中,并具有以下基准,特别是针对用于代替现有 NEC2 高斯消除算法的 zgetrf() 和 zgetrs()。请务必为您的应用程序运行您自己的基准测试,结果会有所不同。

在 Ubuntu 20.04 中,我们选择的库如下:

  • ~# update-alternatives --config libblas.so.3-x86_64-linux-gnu
  • ~# update-alternatives --config liblapack.so.3-x86_64-linux-gnu

在 CentOS/RHEL 中,您拥有以下库,无需使用即可直接访问它们alternatives

  • libopenblas.so:序列号
  • libopenblas o .so:OpenMP
  • libopenblas p .so:pthreads

以下是测试 Ubuntu 20.04 时从记事本复制粘贴的数字。每个部分的前两行定义了为测试选择的内容。这些测试在 KVM 下的 CentOS 7 VM 上运行,具有 24 个 vCPU,运行在具有 32 个逻辑处理器(16 个内核、32 个线程)的双路 Xeon E5-2450 v2 服务器上。虚拟机管理程序负载较轻,不会对数字造成太大干扰,但肯定会出现一些抖动。

默认 LAPACK+BLAS:

/usr/lib/x86_64-linux-gnu/blas/libblas.so.3
/usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3
  Serial:
    Frequency_Loop elapsed time: 17.540371 seconds
    Frequency_Loop elapsed time: 16.697984 seconds
    Frequency_Loop elapsed time: 15.621345 seconds
    Frequency_Loop elapsed time: 15.515307 seconds
Run Code Online (Sandbox Code Playgroud)

使用阿特拉斯

/usr/lib/x86_64-linux-gnu/atlas/libblas.so.3
/usr/lib/x86_64-linux-gnu/atlas/liblapack.so.3
  Serial:
    Frequency_Loop elapsed time: 12.882587 seconds
    Frequency_Loop elapsed time: 12.233791 seconds
    Frequency_Loop elapsed time: 12.828287 seconds
    Frequency_Loop elapsed time: 12.607457 seconds
Run Code Online (Sandbox Code Playgroud)

将 ATLAS 的 BLAS 与 OpenBLAS 串行混合

/usr/lib/x86_64-linux-gnu/atlas/libblas.so.3
/usr/lib/x86_64-linux-gnu/openblas-serial/liblapack.so.3
  Serial:
    Frequency_Loop elapsed time: 11.757070 seconds
    Frequency_Loop elapsed time: 11.566754 seconds
Run Code Online (Sandbox Code Playgroud)

OpenBLAS 串口

/usr/lib/x86_64-linux-gnu/openblas-serial/libblas.so.3
/usr/lib/x86_64-linux-gnu/openblas-serial/liblapack.so.3
  Serial:
    Frequency_Loop elapsed time: 11.345475 seconds
    Frequency_Loop elapsed time: 12.047305 seconds
    Frequency_Loop elapsed time: 11.693541 seconds
Run Code Online (Sandbox Code Playgroud)

具有 OpenMP BLAS 的 OpenBLAS 串行 LAPACK

/usr/lib/x86_64-linux-gnu/openblas-openmp/libblas.so.3
/usr/lib/x86_64-linux-gnu/openblas-serial/liblapack.so.3
  Serial (or barely threaded, 101%)
    Frequency_Loop elapsed time: 11.049351 seconds
    Frequency_Loop elapsed time: 11.756581 seconds
Run Code Online (Sandbox Code Playgroud)

OpenBLAS OpenMP

/usr/lib/x86_64-linux-gnu/openblas-openmp/libblas.so.3
/usr/lib/x86_64-linux-gnu/openblas-openmp/liblapack.so.3
  Threaded (~400% cpu)
    Frequency_Loop elapsed time: 8.079269 seconds
    Frequency_Loop elapsed time: 8.119229 seconds
    Frequency_Loop elapsed time: 8.329753 seconds
Run Code Online (Sandbox Code Playgroud)

OpenBLAS OpenMP LAPACK 与默认 BLAS

/usr/lib/x86_64-linux-gnu/blas/libblas.so.3
/usr/lib/x86_64-linux-gnu/openblas-openmp/liblapack.so.3
    Frequency_Loop elapsed time: 8.161807 seconds
    Frequency_Loop elapsed time: 8.009399 seconds
Run Code Online (Sandbox Code Playgroud)

具有不同线程限制的 OpenBLAS pthreads。

请注意,限制线程可以减少线程争用并在某些情况下提高性能:

/usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
/usr/lib/x86_64-linux-gnu/openblas-pthread/liblapack.so.3
  Threaded 1400% cpu
    Frequency_Loop elapsed time: 13.181950 seconds
    Frequency_Loop elapsed time: 12.866588 seconds
  OPENBLAS_NUM_THREADS=4
    Frequency_Loop elapsed time: 9.567861 seconds
  OPENBLAS_NUM_THREADS=8
    Frequency_Loop elapsed time: 8.767348 seconds
  OPENBLAS_NUM_THREADS=16
    Frequency_Loop elapsed time: 9.818271 seconds
Run Code Online (Sandbox Code Playgroud)

结果

OpenBLAS 的 OpenMP 似乎在此示例中表现最佳。但是,如果您的代码分区良好,您可能会受益于 fork() 或使用 pthread 完全并行运行。分叉作业和单作业并行性的 _NUM_THREADS 之间的某种平衡可能会很好地发挥作用,但是将分叉与 OpenBLAS 或 ATLAS 的线程相结合会导致争用。

例如,xnec2c 支持 -jNN 选项来指定要运行的频率作业的数量。对于许多频率,以完全 fork()ed 并行性(每个频率一个作业)运行串行 LAPACK 版本通常是最快的,而不是使用更多 OpenBLAS/ATLAS 线程运行更少的并行分叉作业,因为矩阵运算通常会具有以下特点:无法并行化的串行缩减阶段。(参见阿姆达尔定律。)

旁注:如果您为主机重新编译 ATLAS,ATLAS 将会自动调整您的 CPU。OpenBLAS 也可能会做一些这样的事情,但不确定。


N0r*_*ert 5

“为什么?”的答案 问题可能是 - 为许多 CPU 和平台获得通用解决方案。

从技术上讲,所有这些二进制包都来自同一个openblas 源包

如果我们谈论为update-alternatives提供的库变体,那么sudo apt-get install "*openblas*"我们可以计算 4 个组和 4 个选项:

$ sudo update-alternatives --config libopenblas<Tab>
libopenblas64.so.0-x86_64-linux-gnu  libopenblas64.so-x86_64-linux-gnu  
libopenblas.so.0-x86_64-linux-gnu    libopenblas.so-x86_64-linux-gnu
Run Code Online (Sandbox Code Playgroud)

安装后,pthread设置为默认(0 选择)版本。

对于基本的基准测试,我们可以利用旧mkl-test.sh脚本来实现openblas使用update-alternatives.

以下是我的 i7-3537U 第三次运行的结果(越低越快,所有结果以秒为单位):

替代库 科学实验室 朱莉娅 Python 3 与 NumPy 八度
pthread 0.31 0.76 0.31 0.39 0.31
openmp 0.24 0.75 0.22 0.31 0.22
serial 0.17 0.79 0.17 0.27 0.17
阿特拉斯/liblapack 0.31 0.75 0.32 0.52 0.32
lapack/liblapack 0.26 0.76 0.30 0.47 0.28
libmkl_rt (MKL) 0.16 0.76 0.16 0.22 0.16

更好的方法是运行官方基准测试,但我目前无法理解如何运行它们。