CMake构建学习笔记26-OpenBLAS库的构建
1 介绍
BLAS(Basic Linear Algebra Subprograms)和 LAPACK(Linear Algebra Package)是两个广泛使用的高性能数值线性代数库,主要用于科学计算、工程仿真、机器学习等领域。它们通常一起使用,为矩阵和向量运算提供底层支持。不过,更确切地说,BLAS / LAPACK 是一组线性代数操作接口标准规范,确实有官方的实现也就是 Netlib BLAS/LAPACK。不过官方库的实现虽然正确,但是性能比较差,所以厂商和社区提供了高度优化的实现:
| 实现 | 特点 |
|---|---|
| OpenBLAS | 开源,自动优化 CPU 架构,广泛用于 Linux/Python 科学栈 |
| Intel MKL | Intel 官方优化库,性能极佳(尤其在 Intel CPU 上),商业许可(但免费供个人/学术使用) |
| ATLAS | 自动调优 BLAS 实现(较老,逐渐被 OpenBLAS 取代) |
| BLIS | 新一代模块化 BLAS 实现,易于定制 |
| Apple Accelerate | macOS/iOS 内置优化库,包含 BLAS/LAPACK 接口 |
其中 OpenBLAS 是开源免费的,而且性能接近 Intel MKL,文档也比较全,这里就介绍一下 OpenBLAS的构建。
2. 构建
承接之前系列文章《CMake构建学习笔记-目录》的构建思路,具体构建脚本简化如下:
# OpenBLAS.ps1
param(
[string]$Name = "OpenBLAS-0.3.30",
[string]$SourceDir = "../Source",
[string]$Generator,
[string]$InstallDir,
[string]$SymbolDir,
[bool]$Force = $false, # 是否强制重新构建
[bool]$Cleanup = $true # 是否在构建完成后删除源码和构建目录
)
# 目标文件
$DllPath = "$InstallDir/bin/openblas.dll"
# 依赖库数组
$Librarys = @()
# 符号库文件
$PdbFiles = @(
"lib/RELWITHDEBINFO/openblas.pdb"
)
# 额外构建参数
$CMakeCacheVariables = @{
USE_LOCKING = "ON"
BUILD_TESTING = "OFF"
BUILD_SHARED_LIBS = "ON"
BUILD_STATIC_LIBS = "OFF"
BUILD_RELAPACK = "ON"
C_LAPACK = "ON"
}
. ./build-common.ps1 -Name $Name `
-SourceDir $SourceDir `
-InstallDir $InstallDir `
-SymbolDir $SymbolDir `
-Generator $Generator `
-TargetDll $DllPath `
-PdbFiles $PdbFiles `
-CMakeCacheVariables $CMakeCacheVariables `
-MultiConfig $false `
-Force $Force `
-Cleanup $Cleanup `
-Librarys $Librarys
CMake构建的流程都封装到脚本 build-common.ps1 中了,可以直接去代码项目或者之前的文章中查看。不过,其实CMake构建大部分程序的关键在于自定义的构建参数:
BUILD_TESTING、BUILD_SHARED_LIBS、BUILD_STATIC_LIBS的含义就是字面意思,这里就不再说明。C_LAPACK表示使用 C 的 LAPACK 实现而不是 Fortran 的原始实现,就不用额外配置 Fortran 的编译器;BUILD_RELAPACK表示编译递归实现的 LAPACK 子程序,可以提升某些小规模线性代数运算的性能,但会增加库的大小。
还有一个构建选项USE_LOCKING跟多线程相关。默认情况下,OpenBLAS内部使用多线程进行运算。但是OpenBLAS一般使用在程序的底层,程序上层如果也使用多线程的话就会造成线程冲突。根据官方文档[1]的介绍:
If your application is already multi-threaded, it will conflict with OpenBLAS multi-threading. Thus, you must set OpenBLAS to use single thread as following.
- export OPENBLAS_NUM_THREADS=1 in the environment variables. Or
- Call openblas_set_num_threads(1) in the application on runtime. Or
- Build OpenBLAS single thread version, e.g. make USE_THREAD=0 USE_LOCKING=1 (see comment below)
If the application is parallelized by OpenMP, please build OpenBLAS with USE_OPENMP=1With the increased availability of fast multicore hardware it has unfortunately become clear that the thread management provided by OpenMP is not sufficient to prevent race conditions when OpenBLAS was built single-threaded by USE_THREAD=0 and there are concurrent calls from multiple threads to OpenBLAS functions. In this case, it is vital to also specify USE_LOCKING=1 (introduced with OpenBLAS 0.3.7).
这里笔者并没有找到USE_THREAD构建选项,还是保持构建成多线程的版本;同时开启USE_LOCKING,这个配置表示通过加锁的方式保证线程安全。另外,OpenBLAS 的多线程行为是运行时可配置的,可以在运行时动态地关闭多线程:
- 设置环境变量:
OPENBLAS_NUM_THREADS=1。 - 代码中设置:
openblas_set_num_threads(1)。
笔者构建的脚本已经在提交到Git仓库中,可以直接在Windows目录运行:
./BuildCppDependency.ps1 -Generator "Visual Studio 16 2019" `
-MSBuild "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\MSBuild.exe" `
-InstallDir "$env:GISBasic" `
-SymbolDir "$env:GISBasic/symbols" `
-Install OpenBLAS
如果想找到已经构建好的文件,可以在这个Git仓库中找到。

浙公网安备 33010602011771号