1. AMD EPYC 上编译 vasp.6.4.3 到底难在哪

如果你手里是一台 AMD EPYC 9654 或者 9xx4 系列的工作站,想从零把 vasp.6.4.3 编译出来,大概率会经历一段比较折腾的过程。VASP 本身是 Fortran 写的计算化学/材料模拟软件,官方只给源码,编译配置全靠自己写 makefile.include。在 Intel 平台上,用 oneAPI 全家桶基本能一把过;但换到 AMD CPU 上,同样的流程会直接报错,因为编译器默认的指令集优化参数和 AMD 的 Zen4 架构对不上。

这篇文章要解决的就是这个场景:AMD CPU 平台从零编译 vasp.6.4.3 的完整链路,覆盖 oneAPI 环境初始化、AOCC 编译器切换、openmpi 并行库对接,以及安装包校验和算例验证。我会给出可以直接复制的环境变量配置、编译命令和验证动作,让你在本地 AMD 工作站上复现一个能跑起来的 vasp.6.4.3。

先说清楚适合谁看:你有一台 AMD EPYC 或者 Ryzen 的机器,已经装好了 Linux(Ubuntu/CentOS 都行),有 root 或者 sudo 权限,想自己编译 VASP 而不是用别人打包好的二进制。如果你只是想快速跑个算例,那直接找现成的编译产物更省事;但如果你想长期用、想调优、想搞清楚每个参数的作用,那自己编译是绕不开的。

我试过两种路线:一种是 Intel oneAPI 全家桶,另一种是 AMD 自家的 AOCC + AOCL + openmpi。两条路都能走通,但踩的坑不一样。下面按顺序讲,你可以根据自己的偏好选一条,也可以两条都试,对比一下性能。

核心检索词先摆出来:AMD CPU 安装 vasp.6.4.3,涉及 oneapi 环境初始化、AOCC 编译器切换、openmpi 并行库对接。这几个词你记住,后面每一步都会对应到。

在开始之前,确认几个前置条件。第一,你的 CPU 是 AMD EPYC 9xx4 系列或者 Zen4 架构的 Ryzen,因为后面用到的 -march=znver4 和 -axCORE-AVX512 都是针对这个架构的。第二,系统里已经装了 gcc、g++、gfortran、make、wget、tar 这些基础工具,没有的话先 sudo apt install build-essential 或者 sudo yum groupinstall "Development Tools"。第三,VASP 源码包 vasp.6.4.3.tgz 已经下载好,放在你计划编译的目录下。第四,磁盘空间至少留 20GB,编译过程会产生大量中间文件。

还有一个容易被忽略的点:MPI 库的选择。VASP 并行依赖 MPI,你可以用 Intel MPI、OpenMPI 或者 MPICH。在 AMD 平台上,如果你走 AOCC 路线,openmpi 是更自然的选择,因为 AOCC 的 flang 编译器和 openmpi 的兼容性更好。如果你走 oneAPI 路线,那直接用 Intel MPI 就行,省去自己编译 openmpi 的麻烦。

最后提醒一句:编译 VASP 是个体力活,第一次跑通可能要花一两个小时,中间报错很正常。关键是看懂报错信息,定位到是编译器参数问题还是库路径问题。下面我会把两种路线的完整命令都列出来,你照着做就行。

2. TaoToken 前置:编译前先把 API 环境准备好

在正式编译 VASP 之前,我想先花点篇幅讲一个容易被忽略但很实用的前置动作:把 TaoToken 的 API 环境配置好。为什么要在编译前做这件事?因为 VASP 编译过程中你会遇到各种报错,比如 makefile.include 写错了、库路径找不到、编译器参数不兼容,这时候如果能有一个稳定的模型对话接口帮你快速查文档、对比参数、生成配置片段,效率会高很多。

TaoToken 是一个大模型 API 聚合服务,官网是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 入口是 https://taotoken.net/api 。它本身不替代你的编译器,也不参与 VASP 的编译过程,它的作用是在你排障的时候提供一个顺手的查询和生成工具。比如你不确定 -axCORE-AVX512 和 -march=znver4 的区别,可以直接在模型对话里问;比如你想让模型帮你检查 makefile.include 里的库路径有没有写错,也可以直接贴进去。

具体怎么接入?分三步。第一步,去 https://taotoken.net/api-keys 生成一个 API Key,这个 Key 就是你调用接口的凭证。第二步,如果你用的是 Claude Code 或者类似的 coding agent,可以在配置里把 Base URL 指向 https://taotoken.net/api,然后把 Key 填进去。第三步,选一个适合代码和文档理解的模型,比如 Claude 系列或者 GPT 系列,Model ID 按平台文档里给的写。

这里给一个 Claude Code 的配置示例,你可以直接参考:

{
  "base_url": "https://taotoken.net/api",
  "api_key": "sk-你的key",
  "model": "claude-3-5-sonnet-20241022"
}

如果你用的是 Cline 或者别的支持 MCP 的工具,配置逻辑类似:Base URL 填 https://taotoken.net/api,Key 填你生成的,Model ID 按平台文档选。注意,这里的三件套是 Base URL + Key + Model ID,缺一不可。很多人只填了 Key 忘了改 Base URL,结果请求发到默认地址去了,报 401 或者连接失败。

为什么我建议在编译前做这件事?因为 VASP 编译的排障过程是高度依赖文档和经验的。比如你遇到 BRMIX: very serious problems the old and the new charge density differ 这个报错,网上搜到的方案五花八门,有的说降编译等级,有的说改 INCAR 参数,有的说换 MPI 库。这时候如果你有一个能理解上下文、能帮你分析报错原因的模型接口,就能少走很多弯路。

另外,如果你打算长期做 DFT 计算或者 Agent 相关的开发,可以考虑 TaoToken 的 Coding Plan,入口在 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_campaign=rewrite 。它适合那种需要频繁调用模型、做代码生成和排障的场景。不过这个不是必须的,按需选择就行。

配置好之后,你可以先发一个测试请求验证一下:

curl https://taotoken.net/api/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk-你的key" \
  -d '{
    "model": "claude-3-5-sonnet-20241022",
    "messages": [{"role": "user", "content": "VASP 编译时 makefile.include 里 FFLAGS 应该怎么写"}]
  }'

如果返回正常的 JSON 响应,说明环境通了。这一步做完,你就可以安心去编译 VASP 了,遇到问题随时可以查。

需要强调的是,TaoToken 在这里的角色是辅助排障和文档查询,不是编译工具链的一部分。VASP 的编译还是靠你本地的 oneAPI 或者 AOCC。不要指望用 API 去替代编译器,那是两回事。

3. 可复制配置:oneAPI 与 AOCC 两条路线的完整参数

这一节是全文的核心,我会把两条路线的配置都写清楚,你可以直接复制。先讲 oneAPI 路线,再讲 AOCC + openmpi 路线。

3.1 oneAPI 路线:Intel 全家桶在 AMD 上的适配

oneAPI 路线的好处是省事,Intel 的编译器、MKL 数学库、MPI 都是一套的,装完之后环境变量一 source 就能用。坏处是在 AMD CPU 上,默认的 -xHOST 参数会生成 Intel 专属指令集,AMD 跑不了或者跑得慢,需要手动改成 -axCORE-AVX512。

第一步,安装 oneAPI。去 Intel 官网下载 oneAPI Base Toolkit 和 HPC Toolkit,或者用命令行安装:

wget https://registrationcenter-download.intel.com/akdlm/IRC_NAS/xxx/intel-oneapi-base-toolkit.sh
sudo sh intel-oneapi-base-toolkit.sh

安装完成后,source 环境:

source /opt/intel/oneapi/setvars.sh

第二步,进入 VASP 源码目录,复制 oneAPI 的模板:

cd ~/DFT/vasp.6.4.3
cp arch/makefile.include.oneapi makefile.include

第三步,编辑 makefile.include。Intel CPU 上只需要改 CC_LIB、CXX_PARS 和 MKLROOT,但 AMD EPYC 9xx4 系列还需要改 FFLAGS 里的 -xHOST。具体改动如下:

CC_LIB   = icx
CXX_PARS = icpx
MKLROOT  ?= /opt/intel/oneapi/mkl/latest
VASP_TARGET_CPU ?= -axCORE-AVX512
FFLAGS   += $(VASP_TARGET_CPU)

注意,-axCORE-AVX512 的意思是生成 AVX512 指令集,同时保留其他指令集的兼容性。如果你用的是 Zen4 架构,AVX512 是支持的,所以这个参数没问题。如果你用的是更老的 AMD CPU,比如 Zen2 或者 Zen3,那可能需要改成 -march=znver2 或者 -march=znver3。

第四步,编译。如果你只需要标准版 vasp_std,直接:

make std

编译完成后,二进制文件在 bin/ 目录下。把它加到 PATH:

export PATH=$PATH:~/DFT/vasp.6.4.3/bin

3.2 AOCC + openmpi 路线:AMD 自家工具链

AOCC 是 AMD Optimizing C/C++ Compiler,基于 LLVM,针对 Zen 架构做了优化。AOCL 是 AMD Optimizing CPU Libraries,包含 BLIS、libFLAME、scaLAPACK、FFTW 等数学库。openmpi 是并行库。这条路线的配置更复杂,但理论上对 AMD CPU 的优化更好。

第一步,安装 AOCC。下载 aocc-compiler-4.2.0.tar.gz,解压到 /home/wliu/software/AMD/aocc-compiler-4.2.0。然后 source 环境:

export COMPILEROOT=/home/wliu/software/AMD/aocc-compiler-4.2.0
export LD_LIBRARY_PATH=$COMPILEROOT/lib:$LD_LIBRARY_PATH
export PATH=$COMPILEROOT/bin:$PATH
export INCLUDE=$COMPILEROOT/include:$INCLUDE
which clang

第二步,安装 AOCL。下载 aocl-linux-aocc-4.2.0.tar.gz,解压后运行安装脚本:

tar -zxvf aocl-linux-aocc-4.2.0.tar.gz
cd aocl-linux-aocc-4.2.0
./install.sh -t /home/wliu/software/AMD/aocl

第三步,写一个构建脚本 build_vasp_aocc_ompi_aocl.sh,把 openmpi 的编译和 VASP 的编译串起来。这个脚本比较长,我把它拆成几段讲。

先设置路径和环境变量:

export SOURCES=$PWD
export COMPILEROOT=/home/wliu/software/AMD/aocc-compiler-4.2.0
export OPENMPIROOT=/home/wliu/software/openmpi
export AOCLROOT=/home/wliu/software/AMD/aocl/4.2.0/aocc
export VASPROOT=$SOURCES/vasp.6.4.3
export ARCH=znver4
export CC=clang
export CXX=clang++
export FC=flang
export F90=flang
export F77=flang

然后编译 openmpi:

cd openmpi-5.0.3
./configure --prefix=$OPENMPIROOT CC=${CC} CXX=${CXX} FC=${FC} \
  CFLAGS="-O3 -march=$ARCH" CXXFLAGS="-O3 -march=$ARCH" \
  FCFLAGS="-O3 -march=$ARCH" LDFLAGS="-march=$ARCH" \
  --enable-mpi-fortran --enable-shared=yes --enable-static=yes \
  --enable-mpi1-compatibility --disable-hwloc-pci
make -j 32
make install

接着编译 VASP 的 fftlib:

cd $VASPROOT/src/fftlib
clang++ -fopenmp -std=c++11 -I./include -I$AOCLROOT/include_LP64 \
  -DFFTLIB_THREADSAFE -c src/fftlib.cpp

最后生成 makefile.include 并编译:

cd $VASPROOT
cat > makefile.include << 'EOF'
CPP_OPTIONS= -DHOST=\"LinuxAMD\" -DMPI -DMPI_BLOCK=8000 -Duse_collective \
  -DscaLAPACK -DCACHE_SIZE=4000 -Davoidalloc -Duse_bse_te -Dtbdyn \
  -Dfock_dblbuf -Dvasp6 -D_OPENMP -Dshmem_bcast_buffer -Duse_shmem \
  -Dsysv -Dfftw_cache_plans -Duse_fftw_plan_effort
CPP = flang -E -P -C -w -Mfree $*.F >$*.f
FC = mpif90 -fopenmp
FCL = mpif90 ${VASPROOT}/src/fftlib/fftlib.o -fopenmp
FFLAGS = -w -march=znver4 -fno-fortran-main $(CPP_OPTIONS) -Mbackslash
OFLAG = -O2
AOCLROOT = /home/wliu/software/AMD/aocl/4.2.0/aocc
BLAS = ${AOCLROOT}/lib/libblis-mt.a
LAPACK = ${AOCLROOT}/lib/libflame.so
SCALAPACK = ${AOCLROOT}/lib/libscalapack.a
LLIBS = $(SCALAPACK) $(LAPACK) $(BLAS) -lstdc++
FFTW ?= ${AOCLROOT}
LLIBS += -L$(FFTW)/lib/ -lfftw3 -lfftw3_omp
INCS = -I$(FFTW)/include_LP64/
OBJECTS = fftmpiw.o fftmpi_map.o fftw3d.o fft3dlib.o
OBJECTS_O1 += fftw3d.o fftmpi.o fftmpiw.o
OBJECTS_O2 += fft3dlib.o
CC_LIB = clang
CFLAGS_LIB = -O
FFLAGS_LIB = -O1
CXX_PARS = clang++ -lstdc++
CXX_FFTLIB = clang++ -fopenmp -std=c++11 -DFFTLIB_THREADSAFE
LLIBS += -ldl -lstdc++
EOF
make std

编译完成后,检查 bin/vasp_std 是否存在。

3.3 两条路线的参数对照

参数oneAPI 路线AOCC 路线
C 编译器icxclang
C++ 编译器icpxclang++
Fortran 编译器ifort/ifxflang
MPIIntel MPIopenmpi 5.0.3
数学库MKLAOCL (BLIS + libFLAME + scaLAPACK)
FFTMKL FFTWAOCL FFTW
指令集参数-axCORE-AVX512-march=znver4
编译命令make stdmake std

这张表你可以存下来,以后换机器或者换版本的时候对照着改。

4. 验证请求:编译产物校验与算例跑通

编译完成不代表就能用,还需要做两步验证:第一步是检查二进制文件是否正常,第二步是跑一个简单算例确认结果合理。

4.1 二进制文件校验

先看 bin/ 目录下有没有 vasp_std:

ls -lh ~/DFT/vasp.6.4.3/bin/

正常应该看到 vasp_std 这个可执行文件,大小在几十 MB 左右。然后检查它依赖的动态库:

ldd ~/DFT/vasp.6.4.3/bin/vasp_std

如果输出里有 not found,说明某个库路径没配好。常见的是 AOCL 的库或者 openmpi 的库找不到。解决办法是把对应的 lib 目录加到 LD_LIBRARY_PATH:

export LD_LIBRARY_PATH=/home/wliu/software/AMD/aocl/4.2.0/aocc/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/home/wliu/software/AMD/aocc-compiler-4.2.0/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/home/wliu/software/openmpi/lib:$LD_LIBRARY_PATH

然后再跑一次 ldd,确认没有 not found。

4.2 算例验证

找一个简单的算例,比如 VASP 官方教程里的 Si 或者 NaCl。把 INCAR、POSCAR、POTCAR、KPOINTS 四个文件准备好,然后运行:

mpirun -np 4 ~/DFT/vasp.6.4.3/bin/vasp_std > vasp.log

跑完之后看 vasp.log 和 OUTCAR。重点看几个地方:第一,vasp.log 里有没有 General timing and accounting informations,有的话说明正常结束。第二,OUTCAR 里看 Total CPU time used 和 Elapsed time,确认计算确实跑了。第三,看能量值是否收敛,比如 free energy TOTEN 这一行。

如果算例跑通了,说明你的 vasp.6.4.3 已经可以正常使用了。接下来可以跑你自己的模型,或者做性能对比。

4.3 性能对比:oneAPI vs AOCC

根据我的初步测试,Intel oneAPI 编译的 VASP 在 AMD EPYC 9654 上跑起来比 AOCC 编译的更快。这个结论可能有点反直觉,因为 AOCC 是 AMD 自家的编译器,理论上应该对 Zen4 优化更好。但实际测试下来,oneAPI 的 MKL 数学库在矩阵运算上的优化确实更强,而 VASP 的计算瓶颈主要在矩阵对角化和 FFT 上。

不过 AOCC 编译的版本有一个问题:出现了 BRMIX: very serious problems the old and the new charge density differ 这个报错。同样的模型和参数,在 oneAPI 编译的版本下没有出现。网上搜到的解决方案包括降低编译等级从 -O3 降到 -O2、在作业脚本里加 export I_MPI_ADJUST_REDUCE=3、在 INCAR 里设 LSCALAPACK=.FALSE.、把 ISYM 设为 0、提高 PREC 和 SYMPREC 的精度、用 10 的倍数的核数运算等等。我试了几个,对我当时的模型都无效。

所以如果你追求稳定性和性能,我建议优先用 oneAPI 路线。AOCC 路线可以作为备选,或者在你需要对比不同编译器优化效果的时候用。

4.4 环境变量持久化

每次开新终端都要重新 source 环境很麻烦,建议把环境变量写到 ~/.bashrc 里:

echo 'source /opt/intel/oneapi/setvars.sh' >> ~/.bashrc
echo 'export PATH=$PATH:~/DFT/vasp.6.4.3/bin' >> ~/.bashrc

如果你用 AOCC 路线,把对应的 export 也加进去。注意,setvars.sh 可能会覆盖一些变量,所以顺序很重要,先 source oneAPI,再设自己的 PATH。

5. 本篇常见错排查:401、local proxy failed、reading choices、OAuth

这一节专门讲排障。VASP 编译和运行过程中会遇到各种报错,我挑几个最常见的,给出原因和解决办法。

5.1 编译时报 makefile.include 相关错误

最常见的报错是 make: *** No rule to make target 'makefile.include'。原因是你在 arch/ 目录下改了模板,但没有复制到源码根目录。解决办法:

cd ~/DFT/vasp.6.4.3
cp arch/makefile.include.oneapi makefile.include

或者如果你用 AOCC,确认 makefile.include 是在 $VASPROOT 根目录下,而不是在 src/ 里。

另一个常见错误是 undefined reference to 'fftw_plan_dft' 之类的链接错误。原因是 FFTW 库路径没写对。检查 makefile.include 里的 FFTW 变量和 LLIBS 里的 -lfftw3 路径。AOCL 的 FFTW 库在 $AOCLROOT/lib/ 下,头文件在 $AOCLROOT/include_LP64/ 下。

5.2 运行时报 BRMIX: very serious problems

这个报错我在 AOCC 编译的版本里遇到过。BRMIX 是 VASP 里负责电荷密度混合的模块,报这个错说明新旧电荷密度差异太大,混合不收敛。可能的原因有几个:编译优化等级太高导致数值精度问题、MPI 归约操作有 bug、或者模型本身的问题。

解决办法按优先级排:第一,把 FFLAGS 里的 -O3 降到 -O2,重新编译。第二,在 INCAR 里加 LSCALAPACK=.FALSE.,禁用 scaLAPACK。第三,把 ISYM 设为 0,关闭对称性。第四,提高 PREC 到 Accurate,提高 SYMPREC 到 1E-6。第五,用 10 的倍数的核数运行,比如 4、8、16、32,避免用 6、12 这种。

如果这些都不行,那可能是 AOCC 编译的版本本身有问题,换 oneAPI 路线试试。

5.3 API 调用时报 401 或 local proxy failed

如果你在配置 TaoToken 的时候遇到 401 Unauthorized,先检查三件事:第一,API Key 有没有填对,有没有多余的空格。第二,Base URL 是不是 https://taotoken.net/api,注意结尾没有斜杠。第三,请求头里的 Authorization 格式是不是 Bearer sk-xxx。

如果报 local proxy failed,说明你的请求没有发到 TaoToken 的服务器,而是被本地代理拦截了。检查你的环境变量里有没有 HTTP_PROXY 或者 HTTPS_PROXY,有的话先 unset:

unset HTTP_PROXY
unset HTTPS_PROXY

然后再试。

5.4 模型返回 reading choices 错误

这个报错通常出现在你调用模型接口的时候,返回的 JSON 里没有 choices 字段。原因可能是 Model ID 写错了,或者请求体格式不对。检查你的请求:

{
  "model": "claude-3-5-sonnet-20241022",
  "messages": [{"role": "user", "content": "test"}]
}

确认 model 字段是平台支持的 Model ID,messages 是数组格式。如果还不行,去 https://taotoken.net/doc 查一下最新的接口文档。

5.5 OAuth 相关错误

如果你用的是 Claude Code 或者类似的工具,可能会遇到 OAuth 认证失败。这种情况通常是因为工具默认走了 OAuth 流程,而不是 API Key 流程。解决办法是在配置里显式指定 API Key,关掉 OAuth。具体配置参考第 2 节的 JSON 示例。

5.6 编译时 mpif90: command not found

这个错误说明 openmpi 的 bin 目录没加到 PATH 里。检查:

which mpif90

如果没有输出,说明 PATH 没配好。加上:

export PATH=$OPENMPIROOT/bin:$PATH

然后再 which mpif90,应该能看到路径。

5.7 运行时报 error while loading shared libraries

这个错误说明动态库找不到。用 ldd 检查:

ldd ~/DFT/vasp.6.4.3/bin/vasp_std | grep "not found"

把缺失的库对应的 lib 目录加到 LD_LIBRARY_PATH。常见的缺失库包括 libblis-mt.so、libflame.so、libscalapack.so、libmpi.so。

6. 语义一致 CTA:编译完成后怎么继续用

VASP 编译完成只是第一步,后面还有很长的路要走。这一节给几个实用的后续动作。

第一,把编译好的二进制备份。bin/vasp_std 这个文件是你花了一两个小时编译出来的,建议复制一份到安全的地方:

cp ~/DFT/vasp.6.4.3/bin/vasp_std ~/backup/vasp_std_oneapi_amd

第二,记录你的编译配置。把 makefile.include 和构建脚本保存下来,以后换机器或者升级版本的时候可以直接复用。我习惯在 ~/DFT/ 下建一个 configs/ 目录,专门放这些配置文件。

第三,做性能基准测试。找几个不同大小的算例,分别用 oneAPI 和 AOCC 编译的版本跑一遍,记录 Elapsed time。这样你就知道在你的具体硬件上,哪个版本更快。注意,性能对比要在相同的核数、相同的 INCAR 参数下做,否则没有意义。

第四,如果遇到编译或者运行问题,可以用 TaoToken 的模型对话接口快速查文档、对比参数。入口在 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_campaign=rewrite 。比如你不确定某个 FFLAGS 参数的含义,直接问就行。

第五,如果你打算长期做 DFT 计算或者开发 Agent 工具,可以看看 TaoToken 的 Coding Plan,入口在 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_campaign=rewrite 。它适合需要频繁调用模型、做代码生成和排障的场景。

第六,接入文档和 API Keys 的入口在这里:API Keys 在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_campaign=rewrite ,接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_campaign=rewrite 。如果你在配置过程中遇到问题,先查文档,文档里没有的再问模型。

最后说一个我踩过的坑:不要用 root 用户编译 VASP。虽然技术上可行,但编译过程中产生的文件权限会变成 root,后面用普通用户跑计算的时候会各种权限报错。用普通用户编译,用普通用户运行,省心。

还有一个实用技巧:编译的时候用 tee 把日志存下来。比如:

make std 2>&1 | tee make.log

这样如果编译失败,你可以直接看 make.log 里的报错信息,不用在终端里翻。而且如果你要用模型帮你分析报错,直接把 make.log 贴进去就行。

编译 VASP 是个耐心活,第一次跑通之后,后面就顺了。祝你编译顺利。

更多推荐