走进向量计算:从源码编译 OpenBLAS

2023-03-05 17:17:02 浏览数 (1)

不论是折腾深度学习、高性能计算,还是折腾向量数据库、相似性检索领域,在折腾的过程中,我们都可能会遇到需要 “OpenBLAS” 这个开源矩阵计算库的场景。

这是因为泛 AI 领域离不开矩阵计算,而 OpenBLAS 是全球前三的开源矩阵计算库。本篇文章,我们就来聊聊 OpenBLAS 在 Linux 和 macOS 环境中的编译和构建。

写在前面

OpenBLAS 在 GitHub 上的项目概况

OpenBLAS 官方项目从 v0.3.6 版本[1]开始,提供了 有限的 “预构建”二进制版本,可以帮助我们节约一些时间。

但是在一些场景下,我们可能需要从源码进行编译:

•比如,我们使用了官方未提供二进制版本的 OpenBLAS•或者,我们需要在某些 CPU 平台 / 架构中来使用 “native” 的库,不能直接使用官方提供的现成的二进制文件

虽然,有一些 Linux 发行版的软件包仓库中提供了 OpenBLAS 的软件包,但是并不是每个发行版中都能够简单快速的安装到比较新的软件版本,比如 Ubuntu 18.04 里最新可用的版本是 0.2.20,Ubuntu 20.04 中最新的版本 0.3.8,只有在 Ubuntu 22.04 中,我们才能够看到 0.3.20 版,流行的用于制作容器的 Linux 发行版 Alpine 里的 OpenBLAS 也是如此。

但是,我们的实际生产环境和业务场景中,遇到老的操作系统,还是蛮常见的,使用固定的非最新版的软件的需求,也是蛮常见的。所以,为了解决这个问题,我们就需要了解如何使用源码编译它。

Ubuntu 环境下编译 OpenBLAS

在 2022 年,我们已经没有理由再使用 Ubuntu 20.04 / 22.04 之外的 LTS 作为生产环境。想在这两个环境中,使用上 “stable” 版本的 OpenBLAS,还是有一些细节上的不同的。

我们先从 Ubuntu 20.04 这个 LTS 版本聊起。

Ubuntu 20.04 环境的 OpenBLAS

Ubuntu 20.04 的软件包仓库[2]中,我们能够找到的最新的 OpenBLAS 版本是 0.3.8,假如我们需要使用的 OpenBLAS 版本是 0.3.9 ,那么我们的问题解决方案,就只有一种:从源码编译。

先执行下面的命令,安装必要的依赖工具:

代码语言:javascript复制
sudo apt-get update && 
# common utils for download sources tarball/zipball
sudo apt-get install -y --no-install-recommends curl wget ca-certificates gnupg2 && 
# openblas deps
sudo apt-get install -y --no-install-recommends g   gcc gfortran git make && 
# cleanup
sudo apt-get remove --purge -y

接着,下载我们所需要版本(0.3.9)的 OpenBLAS 源代码压缩包:

代码语言:javascript复制
OPENBLAS_VERSION=0.3.9 && 
wget "https://github.com/xianyi/OpenBLAS/archive/v${OPENBLAS_VERSION}.tar.gz"

在下载完毕之后,将压缩包进行解压缩,并切换工作目录到代码目录中:

代码语言:javascript复制
OPENBLAS_VERSION=0.3.9 && 
tar zxvf v${OPENBLAS_VERSION}.tar.gz && cd OpenBLAS-${OPENBLAS_VERSION}

然后,根据自己的需求,对 OpenBLAS 进行编译操作:

代码语言:javascript复制
sudo make TARGET=CORE2 DYNAMIC_ARCH=1 DYNAMIC_OLDER=1 USE_THREAD=0 USE_OPENMP=0 FC=gfortran CC=gcc COMMON_OPT="-O3 -g -fPIC" FCOMMON_OPT="-O3 -g -fPIC -frecursive" NMAX="NUM_THREADS=128" LIBPREFIX="libopenblas" LAPACKE="NO_LAPACKE=1" INTERFACE64=0 NO_STATIC=1

编译时间,会根据你的机器的配置而不同。8c16t 的笔记本十分钟不到就能够编译完毕,一台 4c8g 的云主机(虚拟机)可能要构建个把小时。所以需要一些耐心,以及根据自己的资源,适当使用 tmuxscreen 来保持任务运行也是必要的。如果你的机器核心数比较少,可能时间会略漫长,可以起身活动活动,喝杯饮料,瞭望下远方。

当我们看到类似下面的内容的时候,OpenBLAS 的编译就完成了:

代码语言:javascript复制
...
make[1]: Leaving directory '/app/OpenBLAS-0.3.9/exports'

 OpenBLAS build complete. (BLAS CBLAS LAPACK LAPACKE)

  OS               ... Linux             
  Architecture     ... x86_64               
  BINARY           ... 64bit                 
  C compiler       ... GCC  (command line : gcc)
  Fortran compiler ... GFORTRAN  (command line : gfortran)
  Library Name     ... libopenblas-r0.3.9.a (Single threaded)  

To install the library, you can run "make PREFIX=/path/to/your/installation install".

然后,我们来进行 OpenBLAS 的安装:

代码语言:javascript复制
sudo make -j4 PREFIX=/usr NO_STATIC=1 install 

不出意外的话,你将看到类似下面的日志输出,包含了 “Install OK”:

代码语言:javascript复制
...
make[1]: Entering directory '/app/milvus/OpenBLAS-0.3.9'
Generating openblas_config.h in /usr/include
Generating f77blas.h in /usr/include
Generating cblas.h in /usr/include
Copying LAPACKE header files to /usr/include
Copying the shared library to /usr/lib
Generating openblas.pc in /usr/lib/pkgconfig
Generating OpenBLASConfig.cmake in /usr/lib/cmake/openblas
Generating OpenBLASConfigVersion.cmake in /usr/lib/cmake/openblas
Install OK!
make[1]: Leaving directory '/app/milvus/OpenBLAS-0.3.9'

当然,别忘记做收尾工作,清理不必要的“过程产物”:

代码语言:javascript复制
OPENBLAS_VERSION=0.3.9 && 
cd .. && 
rm -rf OpenBLAS-${OPENBLAS_VERSION} && 
rm v${OPENBLAS_VERSION}.tar.gz

如果你需要构建其他版本的 OpenBLAS,可以将命令中的 OPENBLAS_VERSION=0.3.9 中的版本号,修改为你需要的版本。

如果我们能够接受,使用更新一些版本的 OpenBLAS 来替代指定的版本。也可以考虑直接使用 GitHub 中,OpenBLAS 官方提供的最新版本的预构建二进制[3]文件,不少版本都包含了 x86_64 架构的二进制文件。

当然,这样做的前提是,你经过了充分的性能测试验证,确保计算效率能够符合你自己预期。

Ubuntu 22.04 环境的 OpenBLAS

在 Ubuntu 22.04 的环境中,相比较 Ubuntu 20.04,在不追求指定版本的情况下,除了从源码编译构建之外,我们的选择 可以多一种

如果我们能够接受,使用更新一些版本的 OpenBLAS。除了和上文一样,从官方 GitHub 发布页面下载预构建好的二进制文件之外,还能使用 apt install 来下载安装 Ubuntu 软件包仓库中的新版本 OpenBLAS 的软件包[4]

代码语言:javascript复制
sudo apt-get update && 
sudo apt-get install libjulia-openblas64

不过,需要注意的是,这个软件包是由 Ubuntu 社区团队维护的(Ubuntu MOTU Developers),而非 Ubuntu 官方团队,软件包名称也并非 lib-openblas,而是 libjulia-openblas64,所以在长期使用的场景中,软件包可靠性还需要根据自己的场景来评估和衡量。

macOS 环境的 OpenBLAS

在 OpenBLAS 的官方仓库中,我们可以看到官方直到 2021 年 3 月才开始完善 Apple M1 的支持[5](毕竟搭载 M1 的设备 2020 年末才发布)。所以,在 macOS 环境中,如果是 M1 设备(ARMv64),势必需要妥协 OpenBLAS 不能使用某些比较老的版本,需要升级到比较新的版本上来。

加之最近几年 Apple 已经下掉了所有的能够用于生产开发的 x86 Mac 产品,所以像 在 Ubuntu 低版本中折腾 OpenBLAS 编译构建那样,在 macOS 环境中折腾 OpenBLAS 的构建,意义真的不大。

多数场景中,我们直接使用 brew install openblas 命令,就能完成 openblas 的安装了(新版本的预构建二进制):

代码语言:javascript复制
brew install openblas
==> Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/openblas-0.3.20.arm64_monterey.bottle.tar.gz
######################################################################## 100.0%
==> Pouring openblas-0.3.20.arm64_monterey.bottle.tar.gz
==> Caveats
openblas is keg-only, which means it was not symlinked into /opt/homebrew,
because macOS provides BLAS in Accelerate.framework.

For compilers to find openblas you may need to set:
  export LDFLAGS="-L/opt/homebrew/opt/openblas/lib"
  export CPPFLAGS="-I/opt/homebrew/opt/openblas/include"

==> Summary



	

0 人点赞