一、 intel 2016
为了在 AMD cpu 上使用 MKL_DEBUG_CPU_TYPE=5
环境变量从而提高计算速度,只能选择 2020 之前版本的 intel 编译器。以前一直用的是 intel parallel studiox XE 2016 update 3,于是拿来尝试。安装过程中提示不支持的 OS(毕竟这个版本比较老了,当时显然还没有22.04),不过不用管它直接安装即可。装完后编译 fftw3xf 也没出现问题。于是安装 vasp6.4,结果一开始就遇到了如下问题:
make libdmy.a
make[1]: 进入目录“/home/XXXX/ProgramFiles/vasp/vasp6.4.0-i16/build/std/lib”
icc -march=core-avx2 -O -c -o derrf_.o derrf_.c
In file included from derrf_.c(5):
/opt/intel2016u3/include/math.h(1214): error: identifier "_LIB_VERSION_TYPE" is undefined
_LIBIMF_EXT _LIB_VERSIONIMF_TYPE _LIBIMF_PUBVAR _LIB_VERSIONIMF;
^
compilation aborted for derrf_.c (code 2)
make[1]: *** [makefile:31:derrf_.o] 错误 2
make[1]: 离开目录“/home/XXXX/ProgramFiles/vasp/vasp6.4.0-i16/build/std/lib”
make: *** [makefile:18:all] 错误 2
试了下用系统自带的 gcc 11.3 可以编译过去,于是就把 c/c++ 编译器改成了 gcc/g++,这样倒是编译了过去。可是,运行的时候却出现了问题,串行运行时正常,然而 mpi 并行时会卡在自洽循环之前,一直不开始自洽。我以为是 intel + gcc 混合编译的原因,于是想会不会是因为系统里的 gcc 版本太高了,毕竟 intel 编译器也要依赖系统的 libc 以及 libstdc++ 库。想到 CentOS7 上的 gcc 4.8.5 与 intel 2016 配合的挺好,于是想到安装一个低版本的 gcc4 试试,于是装了一个 gcc 4.9.4。然后再重新编译 vasp,c/c++ 编译器改回 icc/icpc,结果同样遇到了上面的错误,网上说可以给 icc 加上选项 -D__PURE_INTEL_C99_HEADERS__
解决,试了下果然编译过去了。于是尝试新编译的 vasp,结果问题依旧,仍是串行能算但并行卡住。从 CentOS7 上拷来的编译好的 vasp 也是一样症状。心想既然上面的 -D... 选项能解决之前的错误,要不再试试就在系统的 gcc 环境下但仍是使用 icc/icpc 编译,结果上面的错误倒是没有了,但是后面却又出现了一大堆的编译错误,和系统里的 c++ 头文件比如 /usr/include/c++/11/bits/stl_uninitialized.h 有关,不知如何解决。看来 intel 2016 相对于 ubuntu 22.04 是太老了,问题一堆。
不过,如果用 2016 的 mpirun 运行一个很久以前编译的 vasp53(应该是 intel 2013 编译的)程序倒是能够正常并行,并不卡住。
【卡住问题解决】后来把解决 intel 2018 并行问题的环境变量 I_MPI_SHM_LMT=shm
用到 intel 2016 上,结果发现并行卡住的问题竟然解决了!看来只是参数设置问题,只不过 2018 有提示而且直接出错,表现不是卡住;而 2016 却表现为卡住而且没有任何提示,很是坑人!而且,最初混合 intel 2016 和 gcc/g++ 11.3 进行编译得到的程序也能正常运行了,其卡住的原因一样,并不是编译问题,而且最终效率和 gcc4 环境下编译出的基本一样。
二、intel 2019
于是尝试换个较新的版本,但还得是 2020之前的,于是就又装了 2019u5。结果,2019 又有新问题,在编译 fftw3xf 时竟然不通过, 出现了如下错误
icc -Wall -Werror -I/opt/intel2019/compilers_and_libraries_2019.5.281/linux/mkl/include -I/opt/intel2019/compilers_and_libraries_2019.5.281/linux/mkl/include/fftw -c /opt/intel2019/compilers_and_libraries_2019.5.281/linux/mkl/interfaces/fftw3xf/wrappers/fftw_alignment_of.c -o obj_intel/fftw_alignment_of.o
In file included from /usr/include/x86_64-linux-gnu/bits/floatn.h(119),
from /usr/include/stdlib.h(56),
from /opt/intel2019/compilers_and_libraries_2019.5.281/linux/mkl/include/fftw/fftw3_mkl.h(25),
from /opt/intel2019/compilers_and_libraries_2019.5.281/linux/mkl/interfaces/fftw3xf/wrappers/fftw_alignment_of.c(22):
/usr/include/x86_64-linux-gnu/bits/floatn-common.h(214): error: invalid combination of type specifiers
typedef float _Float32;
^
......
这个问题搜了一下也没能解决,于是干脆直接用 2016 版里的 libfftw3xf_intel.a,最后倒是编译出来了。然而,运行的时候又出了问题!一开始是由于我直接修改的 2016 版的 module file,导致少写了如下环境变量 prepend-path FI_PROVIDER_PATH ${I_MPI_ROOT}/libfabric/lib/prov
,于是 mpirun 运行时出错,最后是直接使用 intel 自带的环境设置后比较差异发现的问题。这回虽然是能运行了,但是运行时也出现了问题,不论并行串行,运行时一直出现如下警告
WARNING: Sub-Space-Matrix is not hermitian in DAV 16
2.612206137452897E-002
WARNING: Sub-Space-Matrix is not hermitian in DAV 17
3.153763890465701E-002
WARNING: Sub-Space-Matrix is not hermitian in DAV 18
1.912157485711074E-002
WARNING: Sub-Space-Matrix is not hermitian in DAV 19
1.548749765306514E-002
最后虽然运行完毕,但是结果明显有问题,根本不收敛。而如果用 2019 的 mpirun 运行之前编译的那个 vasp53 则直接出错,如果并行而是在 2019 的环境下串行运行 vasp53 虽然不出错,但是却会出现和上面一样的警告!
三、intel 2017, 2018
网上有人说 2019, 2020 版编译器编出的 vasp 可能会有问题,至少 2019 确实是有问题,于是想要不再降低下版本,试下 2017 和 2018。结果,谁知道这两个版本都无法在 ubuntu 22.04 上安装,安装过程中都会出现如下错误而自动退出,估计是认为系统不支持吧
./install.sh: 第 644 行: 417382 段错误 (核心已转储) "$pset_engine_cli_binary" --tmp_dir "$user_tmp" --TEMP_FOLDER "$temp_folder" --download_dir "$download_tmp" $params
唉,装不上就算了。后来又在 CentOS7 + AMD cpu 上试了一下,发现同样问题,也装不上,难道是 CPU 的问题?于是又在 CentOS7 + intel cpu 上试了一下,竟然也同样问题装不上!看来是下载的安装文件有问题?
估计是安装文件有问题,我下的是 2018u4。我从王老师那里要来了 2018u0 版本,就能顺利的安装,编译 fftw3xf 也很正常。只是在编译 vasp 时出现了类似 2016 的问题,那就是在编译 build/std/parser 目录下的 sites.cpp 时
$ icpc -march=core-avx2 -D YY_parse_DEBUG=1 -c sites.cpp -o sites.o
出现了如下一系列错误
In file included from /usr/include/c++/11/bits/stl_algobase.h(59),
from /usr/include/c++/11/vector(60),
from sites.hpp(4),
from sites.cpp(1):
/usr/include/x86_64-linux-gnu/c++/11/bits/c++config.h(491): error: function call is not allowed in a constant expression
#if __has_builtin(__builtin_is_constant_evaluated)
^
应该是和系统的 c++ 头文件版本过高有关。无奈,将 gcc 环境设为 4.9.4 后这些问题就没有了,顺利编译成功。而且我还发现,虽然编译时的环境是 gcc 4.9.4,但是运行时就用 intel 2018 + 默认的 gcc11.3 也能运行,结果一切正常,而且似乎还快了那么一点点。看来只有在编译的时候有必要用 gcc4 的环境。 不过,串行没问题,mpi 并行时还是遇到一点问题,一开始直接提示如下错误
Fatal error in PMPI_Alltoallv: Other MPI error, error stack:
PMPI_Alltoallv(665).............: MPI_Alltoallv(sbuf=0xce86100, scnts=0xc9fb1c0, sdispls=0xc070d40, MPI_DOUBLE_COMPLEX, rbuf=0xce44f40, rcnts=0xc070cc0, rdispls=0xc070bc0, MPI_DOUBLE_COMPLEX, comm=0xc4000002) failed
MPIR_Alltoallv_impl(416)........: fail failed
MPIR_Alltoallv(373).............: fail failed
MPIR_Alltoallv_intra(226).......: fail failed
MPIR_Waitall_impl(221)..........: fail failed
PMPIDI_CH3I_Progress(623).......: fail failed
pkt_RTS_handler(317)............: fail failed
do_cts(662).....................: fail failed
MPID_nem_lmt_dcp_start_recv(302): fail failed
dcp_recv(165)...................: Internal MPI error! Cannot read from remote process
Two workarounds have been identified for this issue:
1) Enable ptrace for non-root users with:
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
2) Or, use:
I_MPI_SHM_LMT=shm
不过好在里面已经提示了解决办法,那就是设置环境变量 I_MPI_SHM_LMT=shm
,设完了就能正常并行了,虚惊一场,以为 2018 也有问题呢。参考 http://cali2.unilim.fr/intel-mpi/doc/Reference_Manual/Shared_Memory_Control.htm。该环境变量好像是用于控制大消息传输的方式,试了一下设成 0 也能运行且效率差不多,但设成 direct 则不行。
四、intel oneAPI 2023
既然老版本的编译器有各种各样的问题,最后我也不执着于是否能用 MKL_DEBUG_CPU_TYPE=5
了,于是干脆装最新的 intel 编译器。近几年来,intel parallel studio 系列已经不出了,升级成了 intel oneAPI,而且是免费的。需要注意的是得安装两个,一个是 oneAPI Base Toolkit 另一个是 oneAPI HPC Toolkit,因为 MKL 库在 Base 里而 MPI 及 Fortran 在 HPC 里。我一开始只安装了 HPC 的发现里面没有 MKL,于是又装的 Base。附:
Base下载地址:https://www.intel.com/content/www/us/en/developer/tools/oneapi/base-toolkit-download.html
HPC下载地址:https://www.intel.com/content/www/us/en/developer/tools/oneapi/hpc-toolkit-download.html
另外参考如下两篇内容:
https://zhuanlan.zhihu.com/p/427743966
https://blog.qiql.net/archives/intelgcc
需要注意的是安装时不必装它的 python 环境,也不必装 eclipse。装完后在安装目录下直接就有一个 setvars.sh 脚本,source 它就直接设置了环境变量。虽然它也提供了
modulefiles-setup.sh 脚本,但是却是针对每个组件单独生成一个文件,导致又一大堆文件生成,使用起来并不方便。而手动写 module file 也是很麻烦的事,因为环境变量太多了。不过可以借助于 env2 工具,它可以自动生成 module file。在一个没有运行 setvars.sh 的 shell 下运行
env2 -from bash -to modulecmd /path/to/setvars.sh
就会生成一个 env2.modulecmd 文件,它就是自动生成的 module file,放到合适地方并重命名即可。注意 env2 是根据比较运行了 setvars.sh 前后的环境变量的变化而工作的,所以如果运行前后环境变量不变则生成结果为空。
用装好的 2023 版编译器进行编译,首先 fftw3xf 编译正常,然后编译 vasp。注意两点,一是 -mkl
改为 -qmkl
,而是去掉 -xHOST
,然后就顺利编译通过了。最后运行 vasp 无论串行并行都正常,结果也正常。看来还是最新的编译器与新系统兼容。
试了下在 2023 的环境下运行那个以前编译的 vasp53,串行时提示如下错误
vasp53: symbol lookup error: /usr/local/opt/intel2023/mkl/2023.1.0/lib/intel64/libmkl_blacs_intelmpi_lp64.so: undefined symbol: MPI_Comm_get_attr
而并行则直接出错退出。
总结
性能上还是 2016 版的最快(MKL_DEBUG_CPU_TYPE=5 对 16、18有效,对23无效),简单测试结果如下:
2016: 串行 355.6s,四核并行 124.6s
2018: 串行 411.0s,四核并行 141.6s
2023: 串行 455.0s,四核并行 216.9s(这个系统耗时长达78s,上面两个则可忽略)gcc 较新的系统(我这里11.3)下装较老版本的 intel 编译器,编译 vasp 时会出现编译错误,因为有部分 c++ 文件用 icpc 编译时要用到系统的头文件,而较新的头文件中会使用较新标准的语法导致 icpc 不支持从而编译失败。解决办法就是装较老版本的 gcc,比如 4.x,然后在较低版本 gcc 环境下再用 icpc 去编译就正常了。
上面说到的 icpc 编译失败的那些程序,其实可以混合编译,即 fortran 部分使用 mpiifort 编译,而 c/c++ 部分则用系统的 gcc/g++ 编译,这样就没有上述编译问题了。
运行环境比编译环境重要,比如 2016 编出的 vasp 在 2018 环境下运行其速度和 2018 的一样;反之,2018 编译出的 vasp 在 2016 环境下运行其速度和 2016 的一样。
对 2016 和 2018 版的编译器,环境变量
I_MPI_SHM_LMT=shm
相当重要,不设的话要么程序并行时卡死,要么直接出错退出!