介紹了稀疏矩陣求解庫 SuiteSparse 的構建方法,基於已構建的 OpenBLAS、gmp 和 mpfr 依賴,使用自動化工具 BuildCppDependency 在 Windows 和 Linux 平台完成編譯,並詳細説明了關鍵 CMake 構建參數的作用。

1 介紹

在上一篇文章《CMake構建學習筆記26-OpenBLAS庫的構建》中介紹的OpenBLAS是用來解決稠密矩陣相關問題的,例如數值優化中的最小二乘問題。但是如果問題模型中的已知參數太多,就會導致求解的矩陣中存在大量的零值,直接使用常規的稠密矩陣方法求解不僅速度慢,對內存資源的消耗也是一個問題。這種存在大量的零值的矩陣就是稀疏矩陣,會採用一些專門的方法優化這一類問題的求解。

SuiteSparse 就是一個用於高效求解稀疏矩陣相關的問題的開源軟件包集合。它由 Timothy A. Davis 教授開發和維護,被廣泛應用於科學計算、工程仿真、圖論、機器學習等領域。

2 構建

SuiteSparse需要3個依賴庫:OpenBLAS、gmp 和 mpfr ,正好這三個依賴庫我們在前面的文章《CMake構建學習筆記26-OpenBLAS庫的構建》和《CMake構建學習筆記28-gmp&mpfr庫的構建》中都介紹過,這裏就不再贅敍了。

還是使用本系列文章(《CMake構建學習筆記-目錄》)實現的自動化工具 BuildCppDependency 來構建 SuiteSparse。在 Windows 平台下輸入指令:

./BuildCppDependency.ps1 `
  -Generator "Visual Studio 16 2019" `
  -InstallDir "$env:GISBasic" `
  -SymbolDir "$env:GISBasic/symbols" `
  -Install SuiteSparse

在 Linux (Ubuntu) 平台下輸入指令:

./build.sh -install SuiteSparse -installdir "$GISBasic"

進一步看一下 Windows 下的構建腳本,主要是為了看一下 CMake 構建參數:

# SuiteSparse.ps1
param(    
    [string]$Name = "SuiteSparse-7.11.0",
    [string]$SourceDir = "../Source",
    [string]$Generator,
    [string]$InstallDir,  
    [string]$SymbolDir,  
    [bool]$Force = $false,        # 是否強制重新構建
    [bool]$Cleanup = $true        # 是否在構建完成後刪除源碼和構建目錄
)

# 目標文件
$DllPath = "$InstallDir/bin/umfpack.dll"

# 依賴庫數組
$Librarys = @("OpenBLAS", "gmp", "mpfr")  

# 符號庫文件
$PdbFiles = @(
    "SuiteSparse_config/RelWithDebInfo/suitesparseconfig.pdb"
    "Mongoose/RelWithDebInfo/suitesparse_mongoose.pdb"
    "AMD/RelWithDebInfo/amd.pdb"
    "BTF/RelWithDebInfo/btf.pdb"
    "CAMD/RelWithDebInfo/camd.pdb"
    "CCOLAMD/RelWithDebInfo/ccolamd.pdb"
    "CHOLMOD/RelWithDebInfo/cholmod.pdb"
    "COLAMD/RelWithDebInfo/colamd.pdb"
    "CXSparse/RelWithDebInfo/cxsparse.pdb"
    "GraphBLAS/RelWithDebInfo/graphblas.pdb"    
    "KLU/RelWithDebInfo/klu.pdb"
    "LAGraph/dlls/RelWithDebInfo/lagraph.pdb"
    "LAGraph/dlls/RelWithDebInfo/lagraphx.pdb"
    "LDL/RelWithDebInfo/ldl.pdb"
    "ParU/RelWithDebInfo/paru.pdb"
    "RBio/RelWithDebInfo/rbio.pdb"
    "SPEX/RelWithDebInfo/spex.pdb"
    "SPEX/RelWithDebInfo/spexpython.pdb"
    "SPQR/RelWithDebInfo/spqr.pdb"
    "UMFPACK/RelWithDebInfo/umfpack.pdb"
) 

# 額外構建參數
$CMakeCacheVariables = @{
    SUITESPARSE_REQUIRE_BLAS = "ON"
    SUITESPARSE_USE_64BIT_BLAS = "ON"   
    BUILD_TESTING = "OFF"
    BUILD_STATIC_LIBS = "OFF"
    BUILD_SHARED_LIBS = "ON"
    SUITESPARSE_USE_FORTRAN = "ON"
    SUITESPARSE_C_TO_FORTRAN = "(name,NAME) name##_"
}

. ./build-common.ps1 -Name $Name `
    -SourceDir $SourceDir `
    -InstallDir $InstallDir `
    -SymbolDir $SymbolDir `
    -Generator $Generator `
    -TargetDll $DllPath `
    -PdbFiles $PdbFiles `
    -CMakeCacheVariables $CMakeCacheVariables `
    -MultiConfig $true `
    -Force $Force `
    -Cleanup $Cleanup `
    -Librarys $Librarys

這幾個構建參數比較關鍵,否者容易構建失敗,這裏就詳細説明一下:

SUITESPARSE_REQUIRE_BLAS = "ON":強制要求在構建 SuiteSparse 時鏈接 BLAS/LAPACK 庫。

SUITESPARSE_USE_64BIT_BLAS = "ON":啓用對 64 位整數索引的 BLAS/LAPACK 接口 的支持(也稱為 ILP64 模式)。默認的 BLAS/LAPACK 使用 32 位整數,當處理超大規模稀疏矩陣時,鏈接的 OpenBLAS 必須編譯為 ILP64 版本,否則會出現鏈接錯誤或運行時崩潰。

BUILD_TESTING = "OFF":禁用測試程序的構建。

BUILD_STATIC_LIBS = "OFF"/BUILD_SHARED_LIBS = "ON":只構建動態鏈接庫,不構建靜態庫。

SUITESPARSE_USE_FORTRAN = "ON":使用傳統的 Fortran 風格 BLAS/LAPACK 接口(如函數名為 dgemm_, dpotrf_ 等)來鏈接外部庫。

SUITESPARSE_C_TO_FORTRAN = "(name,NAME) name##_":定義 C 函數如何調用 Fortran 子程序的命名轉換規則。

儘管在構建 OpenBLAS 的時候,沒有使用 Fortran 來構建,但是處於兼容性,OpenBLAS還是會提供 Fortran 接口。這裏設置了使用傳統的 Fortran 風格來調用 BLAS/LAPACK 接口,但是 SuiteSparse 本身是 C 實現的,因此調用 Fortran 接口需要對接口命名進行轉換。

3. 其他

系列文章:《CMake構建學習筆記-目錄》 構建工具: Github地址,GitCode地址 二進制構建結果:Github地址,GitCode地址