1. 为什么要在 Linux 上自己编译 MUMPS
MUMPS(MUltifrontal Massively Parallel sparse direct Solver)是一套面向稀疏矩阵的并行直接求解器,做有限元、计算流体、结构仿真、电磁场这类工程计算时,经常会遇到 Ax=b 里 A 是几十万甚至上百万阶稀疏矩阵的情况。直接法相比迭代法,优势在于对病态矩阵更稳、多右端项复用分解结果效率高,而 MUMPS 正是这个领域被引用最多的开源实现之一。它支持实数/复数、单精度/双精度、对称/非对称矩阵,还能通过 OpenMP、MPI、BLAS/LAPACK、ScaLAPACK、Scotch、METIS 等组件把性能拉满。
那为什么不直接用 apt 装?Ubuntu 仓库里确实有libmumps-dev,但版本往往落后,编译选项固定,遇到需要 int64 索引、需要和 PETSc 或自研求解框架对接、需要 Debug 符号定位数值问题时,发行版包就不够用了。自己从源码编译,你能控制整数位宽、是否开 OpenMP、链接哪套 BLAS、安装路径和 RPATH,后续排查链接错误也心里有数。
这篇面向的是在 Linux 本地或工作站上,从零把 MUMPS 编译成可执行库并验证可用的完整流程。适合已经会基本 CMake 和 GCC 命令、但没亲手编过 MUMPS 的工程师。我会给出可复制的依赖安装、CMake 配置、编译命令,以及一个真正能跑通的最小验证程序。编译过程中最容易卡住的几个报错,我也会逐个拆开讲。
需要说明的是,编译本身是纯本地行为,不涉及任何网络访问工具;如果你在配置 AI 辅助编码环境时需要统一管理模型调用,可以了解下 TaoToken 这类聚合入口,但本文重点始终放在 MUMPS 编译本身。
2. 编译前的依赖准备与 TaoToken 环境说明
MUMPS 本身不复杂,复杂的是它依赖的数学库链条。核心依赖分三层:底层 BLAS/LAPACK 提供稠密矩阵运算;中间层 Scotch/METIS 提供图划分以降低填充;上层 MPI/ScaLAPACK 提供分布式并行。你可以按需裁剪,但第一次编译建议先把基础组合跑通,再逐步加组件。
在 Ubuntu 22.04 上,最省事的依赖安装方式是用 apt 装 OpenBLAS、LAPACK、Scotch、METIS 和 OpenMPI:
sudo apt update sudo apt install -y build-essential cmake git gfortran \ libopenblas-dev liblapack-dev libscotch-dev libmetis-dev \ libopenmpi-dev openmpi-bin装完后确认版本,避免后面 CMake 找不到:
gcc --version cmake --version mpirun --version ldconfig -p | grep -E "openblas|scotch|metis"如果你追求极致性能,可以换成 Intel oneAPI 的 MKL 和 icx/icpx 编译器。oneAPI 安装后需要 source 环境脚本,让编译器进入 PATH:
source /opt/intel/oneapi/setvars.sh which icx icpx mpiicx这里有个容易忽略的点:oneAPI 自带的 MPI 和系统 OpenMPI 可能冲突,编译时要么统一用 Intel MPI,要么统一用系统 OpenMPI,不要混用,否则链接阶段会出现符号重复或找不到MPI_Init的问题。
关于 TaoToken,它在这里的角色是:当你在调试编译脚本、让 AI 帮你读 CMake 报错、生成 CMakePresets 或写验证程序时,可以通过统一的 API 入口调用不同模型,省去在多个平台间切换。它的 API 地址是 https://taotoken.net/api ,模型对话入口在 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。这些只是辅助工具,和 MUMPS 编译没有强绑定,你完全可以只用本地终端完成全部工作。
依赖装好后,建议先验证 OpenBLAS 能被链接:
echo 'int main(){return 0;}' > t.c gcc t.c -lopenblas -o t && ./t && echo "BLAS link OK"这一步能过,说明基础工具链没问题,可以进入源码编译阶段。
3. 可复制的 MUMPS 源码编译配置
MUMPS 官方源码在 mumps-solver.org,但手动处理它的依赖顺序比较繁琐。社区维护的 mumps-superbuild 把 MUMPS 及其依赖(Scotch、METIS、ScaLAPACK 等)用 CMake ExternalProject 串起来,一条命令就能拉齐,非常适合第一次编译。下面这套流程我在 Ubuntu 22.04 + GCC 11 上实测可用。
先拉源码并切到稳定 tag:
git clone https://github.com/scivision/mumps-superbuild.git cd mumps-superbuild git checkout v5.8.2.0接着创建CMakeUserPresets.json,把编译选项固化下来。这个文件放在仓库根目录,CMake 会自动读取。下面这份配置开启了单双精度、复数、OpenMP、Scotch,关闭了 METIS 和 ScaLAPACK,先用最小依赖跑通:
{ "version": 6, "cmakeMinimumRequired": { "major": 3, "minor": 20, "patch": 0 }, "configurePresets": [ { "name": "linux_default", "hidden": true, "inherits": "default", "binaryDir": "${sourceDir}/out/build/${presetName}", "cacheVariables": { "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}", "CMAKE_BUILD_TYPE": "Release", "BUILD_SINGLE": true, "BUILD_DOUBLE": true, "BUILD_COMPLEX": true, "BUILD_COMPLEX16": true, "MUMPS_parallel": true, "MUMPS_openmp": true, "MUMPS_scotch": true, "MUMPS_metis": false, "MUMPS_scalapack": false, "BUILD_SHARED_LIBS": true } }, { "name": "linux_gcc_release", "hidden": false, "inherits": "linux_default", "displayName": "Linux GCC Release", "generator": "Unix Makefiles", "cacheVariables": { "CMAKE_C_COMPILER": "/usr/bin/gcc", "CMAKE_CXX_COMPILER": "/usr/bin/g++", "CMAKE_Fortran_COMPILER": "/usr/bin/gfortran" } } ], "buildPresets": [ { "name": "linux_gcc_release", "configurePreset": "linux_gcc_release" } ] }几个关键参数解释一下。MUMPS_intsize64控制整数索引位宽,默认 32 位,矩阵规模超过约 20 亿非零元才需要开 64 位,普通工程问题保持默认即可。BUILD_SHARED_LIBS设为 true 生成.so,方便后续动态链接;如果你要做静态部署,改成 false。MUMPS_scotch开启后会用 Scotch 做填充减少,对稀疏直接法性能影响很大,建议保留。
配置和编译:
cmake --preset linux_gcc_release cmake --build --preset linux_gcc_release -j$(nproc)编译过程会依次构建 METIS/Scotch(如果开启)、BLAS 接口、MUMPS 主体,最后安装到out/install/linux_gcc_release。整个流程在 8 核机器上大约 5 到 10 分钟。完成后检查产物:
ls out/install/linux_gcc_release/lib ls out/install/linux_gcc_release/include你应该能看到libdmumps.so、libmumps_common.so、libpord.so以及对应的头文件。到这里,MUMPS 库就编译好了。
4. 验证 MUMPS 库可用的测试请求
编译成功不等于能用,必须写一个最小程序实际调用一次求解,确认链接、符号、运行时库路径都对。下面这个 C 程序构造一个 3x3 的稀疏矩阵,用 MUMPS 求解 Ax=b,然后打印解向量。
新建test_mumps.c:
#include <stdio.h> #include <stdlib.h> #include "dmumps_c.h" #define JOB_INIT -1 #define JOB_END -2 #define USE_COMM_WORLD -987654 int main(void) { DMUMPS_STRUC_C id; int n = 3, nz = 5; int irn[5] = {1, 2, 3, 1, 2}; int jcn[5] = {1, 2, 3, 2, 3}; double a[5] = {2.0, 2.0, 2.0, 1.0, 1.0}; double rhs[3] = {1.0, 2.0, 3.0}; id.comm_fortran = USE_COMM_WORLD; id.par = 1; id.sym = 0; id.job = JOB_INIT; dmumps_c(&id); id.n = n; id.nz = nz; id.irn = irn; id.jcn = jcn; id.a = a; id.rhs = rhs; id.icntl[0] = -1; id.icntl[1] = -1; id.icntl[2] = -1; id.icntl[3] = 0; id.job = 6; dmumps_c(&id); if (id.infog[0] < 0) { printf("MUMPS error: %d\n", id.infog[0]); return 1; } printf("Solution: x1=%.4f x2=%.4f x3=%.4f\n", rhs[0], rhs[1], rhs[2]); id.job = JOB_END; dmumps_c(&id); return 0; }编译并运行,注意把路径换成你自己的安装目录:
MUMPS_DIR=$PWD/out/install/linux_gcc_release gcc test_mumps.c -o test_mumps \ -I${MUMPS_DIR}/include \ -L${MUMPS_DIR}/lib \ -ldmumps -lmumps_common -lpord -lscotch -lscotcherr \ -lopenblas -lpthread -lm \ -Wl,-rpath,${MUMPS_DIR}/lib ./test_mumps如果输出类似Solution: x1=... x2=... x3=...且没有报错,说明 MUMPS 库已经可以正常调用。这里-Wl,-rpath很关键,它把库路径写进可执行文件,避免运行时找不到.so。如果你不想用 rpath,也可以设置环境变量:
export LD_LIBRARY_PATH=${MUMPS_DIR}/lib:$LD_LIBRARY_PATH验证通过后,你就可以在自己的求解框架里链接这套库了。如果后续需要让 AI 帮你生成更复杂的调用代码或解析 MUMPS 的 info 数组含义,可以通过 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 获取 API Key,再配合接入文档使用。
5. 编译与运行中的常见报错排查
这一节把我在编译 MUMPS 时真实踩过的坑列出来,对照报错定位会快很多。
报错一:CMake Error: Could not find SCOTCH
即使你装了libscotch-dev,CMake 有时仍找不到,因为 Scotch 的头文件路径和库名在不同发行版里不一致。解决办法是在 preset 里显式指定:
"SCOTCH_INCLUDE_DIR": "/usr/include/scotch", "SCOTCH_LIBRARY": "/usr/lib/x86_64-linux-gnu/libscotch.so"如果关闭了MUMPS_scalapack却仍提示找不到 scalapack,这是 mumps-superbuild 里config.cmake.in生成MUMPSConfig.cmake时的已知问题,它会把未启用的组件也写进依赖。处理方式是在 CMake 配置时加-DMUMPS_scalapack=OFF并清理out/build缓存后重新配置,不要复用旧缓存。
报错二:undefined reference to 'MPI_Init'
这是 MPI 编译器没对上。如果你用系统 OpenMPI,编译验证程序时要用mpicc而不是gcc:
mpicc test_mumps.c -o test_mumps -I${MUMPS_DIR}/include -L${MUMPS_DIR}/lib -ldmumps -lmumps_common -lpord -lscotch -lscotcherr -lopenblas如果用的是 Intel oneAPI,则用mpiicx。混用会导致符号找不到。
报错三:error while loading shared libraries: libdmumps.so: cannot open shared object file
运行时找不到库,两种解法:编译时加-Wl,-rpath,${MUMPS_DIR}/lib,或者运行时export LD_LIBRARY_PATH=${MUMPS_DIR}/lib:$LD_LIBRARY_PATH。推荐前者,部署时更省心。
报错四:INFOG(1) = -9或-10
这不是编译错误,是运行时 MUMPS 报的。-9通常表示内存不足,-10表示矩阵结构有问题,比如 irn/jcn 索引越界或重复。检查你的稀疏矩阵输入,MUMPS 的索引是 1-based,不是 0-based,这点和很多 C 库不同,容易写错。
报错五:local proxy failed或401
如果你在配置 AI 辅助工具时遇到这类报错,通常是 API Key 或 Base URL 配置不对。以 Cline 或 Claude Code 这类工具为例,需要同时确认三件套:Base URL 填https://taotoken.net/api,Key 从控制台获取,Model ID 按文档填写。三者缺一都会报 401 或代理失败。控制台在 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,配置文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。
报错六:reading choices解析失败
这类报错一般出现在调用模型接口时返回体格式不符合预期,检查请求是否带了正确的Content-Type: application/json,以及模型名是否拼写正确。和 MUMPS 编译无关,但如果你在同一台机器上同时做编译和 AI 辅助开发,容易混淆日志来源,建议分开终端窗口。
排查时养成一个习惯:先看 CMake 配置阶段的输出,再看编译阶段的第一个 error,不要被后面连锁报错带偏。MUMPS 的报错往往第一个才是根因。
6. 把编译好的 MUMPS 接入你的求解流程
库编译并验证通过后,下一步是把它接入实际项目。如果你用 CMake 管理自己的工程,可以在CMakeLists.txt里这样引用:
set(MUMPS_DIR "/path/to/out/install/linux_gcc_release") find_library(DMUMPS_LIB dmumps PATHS ${MUMPS_DIR}/lib REQUIRED) find_library(MUMPS_COMMON_LIB mumps_common PATHS ${MUMPS_DIR}/lib REQUIRED) find_path(MUMPS_INCLUDE_DIR dmumps_c.h PATHS ${MUMPS_DIR}/include REQUIRED) target_include_directories(your_target PRIVATE ${MUMPS_INCLUDE_DIR}) target_link_libraries(your_target PRIVATE ${DMUMPS_LIB} ${MUMPS_COMMON_LIB} openblas)如果你用 PETSc,编译 PETSc 时加--with-mumps-dir=${MUMPS_DIR}就能让 PETSc 自动发现这套 MUMPS,后续用-pc_type lu -pc_factor_mat_solver_type mumps直接调用。
对于长期做稀疏求解、需要反复调试编译参数和求解器配置的场景,可以考虑用 Coding Plan 统一管理模型调用额度,入口在 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,适合把 AI 辅助编码和本地编译流程结合起来用。
最后给一个实用建议:把编译好的 MUMPS 安装目录打包备份,记录下当时的 CMake preset 和编译器版本。稀疏求解器的性能对 BLAS 实现和编译优化等级很敏感,Release 和 Debug 版本的结果可能差几倍,保留一份可复现的构建记录,比事后重新猜参数省事得多。编译完成后先用小矩阵验证正确性,再上大规模问题测性能,这个顺序不要颠倒。