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

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

在 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)

哪一个包可以产生最快的结果?

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

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

答案1

为什么有这么多?

  • -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: 串行
  • 自由开放布拉斯o.so: OpenMP
  • 自由开放布拉斯.so: pthreads

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

默认 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

使用 ATLAS

/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

将 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

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

OpenBLAS 串行 LAPACK 和 OpenMP BLAS

/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

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

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

具有不同线程限制的 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

结果

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

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

附注:如果您为主机重新编译 ATLAS,它将自动调整您的 CPU。OpenBLAS 可能也会执行一些这样的操作,但不确定。

答案2

“为什么?”这个问题的答案可能是——为了获得适用于多种 CPU 和平台的通用解决方案。

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

如果我们谈论提供的库变体更新替代方案,然后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

安装后线程设置为默认(0 个选择)版本。

对于基本的基准测试,我们可以利用我们的旧mkl-test.sh脚本针对openblas使用 的库的不同替代方案update-alternatives

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

Alt 库 科学实验室 朱莉娅 Python 3 与 NumPy R 八度
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
atlas/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

更好的方法是运行官方基准,但我目前不明白如何运行它们。

相关内容