3、构建LAMMPS
3.5.可选的构建设置
LAMMPS 可以通过多种可选设置来构建。每个小节都解释了如何使用 CMake 和 make 进行构建。
3.5.1. C++11 标准合规性
编译 LAMMPS 需要 C++11 标准兼容编译器。 LAMMPS 2020 年 3 月 3 版是核心代码和大多数软件包与之前的 C++98 标准兼容的最后一个版本。当前使用的大多数 C++ 编译器都与 C++11 兼容,但一些较旧的编译器可能需要额外的标志来启用 C++11 合规性。 GNU c++ 4.8.x 的示例:
CCFLAGS = -g -O3 -std=c++11
3.5.2. FFT 库
当 KSPACE 包包含在 LAMMPS 构建中时,kspace_style pppm 命令执行 3d FFT,这需要使用 FFT 库来计算 1d FFT。 KISS FFT 库包含在 LAMMPS 中,但其他库可能更快。如果您的系统上可用,则 LAMMPS 可以使用它们。
2024 年 2 月 7 日版本中的新增功能。
或者,LAMMPS 可以使用 heFFTe 库来实现 MPI 通信算法,该算法针对特殊情况进行了许多优化,例如利用后端库中可用的 2D 和 3D FFT 以及更好的打包和通信流水线。
CMake构建
-D FFT=value # FFTW3 or MKL or KISS, default is FFTW3 if found, else KISS
-D FFT_KOKKOS=value # FFTW3 or MKL or KISS or CUFFT or HIPFFT, default is KISS
-D FFT_SINGLE=value # yes or no (default), no = double precision
-D FFT_PACK=value # array (default) or pointer or memcpy
-D FFT_USE_HEFFTE=value # yes or no (default), yes links to heFFTe
注:当在运行时编译并选择包的 Kokkos 变体时,将应用由 FFT_KOKKOS 变量选择的 FFT 库。否则,应用由 FFT 变量选择的 FFT 库。相同的 FFT 设置适用于两者。 FFT_KOKKOS 必须与 Kokkos 后端兼容 - 例如,当使用 Kokkos 的 CUDA 后端时,必须使用 CUFFT 或 KISS。
通常这些设置就足够了。如果选择 FFTW3,则 CMake 将尝试检测线程 FFTW 库是否可用并默认启用它们。此设置与是否启用 OpenMP 线程以及是否使用 KOKKOS 或 OPENMP 等包无关。如果 CMake 无法检测到 FFT 库,您可以设置这些变量来提供帮助:
-D FFTW3_INCLUDE_DIR=path # path to FFTW3 include files
-D FFTW3_LIBRARY=path # path to FFTW3 libraries
-D FFTW3_OMP_LIBRARY=path # path to FFTW3 OpenMP wrapper libraries
-D FFT_FFTW_THREADS=on # enable using OpenMP threaded FFTW3 libraries
-D MKL_INCLUDE_DIR=path # ditto for Intel MKL library
-D FFT_MKL_THREADS=on # enable using threaded FFTs with MKL libraries
-D MKL_LIBRARY=path # path to MKL libraries
-D FFT_HEFFTE_BACKEND=value # FFTW or MKL or empty/undefined for the stock heFFTe back end
-D Heffte_ROOT=path # path to an existing heFFTe installation
注:heFFTe 带有用于 FFT 的内置(= 库存)后端,即默认的内部 FFT 实现;但是,该库存后端仅用于测试目的,并未针对生产运行进行优化。
传统make
要更改要使用的 FFT 库及其选项,您必须编辑机器 Makefile。下面是如何更改 makefile 变量的示例。
FFT_INC = -DFFT_FFTW3 # -DFFT_FFTW3, -DFFT_FFTW (same as -DFFT_FFTW3), -DFFT_MKL, or -DFFT_KISS
# default is KISS if not specified
FFT_INC = -DFFT_KOKKOS_CUFFT # -DFFT_KOKKOS_{FFTW,FFTW3,MKL,CUFFT,HIPFFT,KISS}
# default is KISS if not specified
FFT_INC = -DFFT_SINGLE # do not specify for double precision
FFT_INC = -DFFT_FFTW_THREADS # enable using threaded FFTW3 libraries
FFT_INC = -DFFT_MKL_THREADS # enable using threaded FFTs with MKL libraries
FFT_INC = -DFFT_PACK_ARRAY # or -DFFT_PACK_POINTER or -DFFT_PACK_MEMCPY
# default is FFT_PACK_ARRAY if not specified
FFT_INC = -I/usr/local/include
FFT_PATH = -L/usr/local/lib
FFT_LIB = -lhipfft # hipFFT either precision
FFT_LIB = -lcufft # cuFFT either precision
FFT_LIB = -lfftw3 # FFTW3 double precision
FFT_LIB = -lfftw3 -lfftw3_omp # FFTW3 double precision with threads (needs -DFFT_FFTW_THREADS)
FFT_LIB = -lfftw3 -lfftw3f # FFTW3 single precision
FFT_LIB = -lmkl_intel_lp64 -lmkl_sequential -lmkl_core # MKL with Intel compiler, serial interface
FFT_LIB = -lmkl_gf_lp64 -lmkl_sequential -lmkl_core # MKL with GNU compiler, serial interface
FFT_LIB = -lmkl_intel_lp64 -lmkl_intel_thread -lmkl_core # MKL with Intel compiler, threaded interface
FFT_LIB = -lmkl_gf_lp64 -lmkl_gnu_thread -lmkl_core # MKL with GNU compiler, threaded interface
FFT_LIB = -lmkl_rt # MKL with automatic runtime selection of interface libs
与 CMake 一样,如果编译器可以在其默认搜索路径中找到 FFT 头文件和库文件,则无需在 FFT_INC
或 FFT_PATH
中设置路径。您必须指定 FFT_LIB
以及要包含在链接中的适当 FFT 库。
传统 make 还可以使用现有安装链接到 heFFTe
include <path-to-heffte-installation>/share/heffte/HeffteMakefile.in
FFT_INC = -DFFT_HEFFTE -DFFT_HEFFTE_FFTW $(heffte_include)
FFT_PATH =
FFT_LIB = $(heffte_link) $(heffte_libs)
heFFTe 安装路径将包含 HeffteMakefile.in。它将定义使用传统 make 从外部项目链接到 heFFTe 所需的 heffte_ include 变量。 -DFFT_HEFFTE 需要切换到使用 heFFTe,而可选的 -DFFT_HEFFTE_FFTW 选择所需的 heFFTe 后端,例如 -DFFT_HEFFTE_FFTW 或 -DFFT_HEFFTE_MKL,省略该变量将默认为库存后端。 heFFTe 库存后端旨在用于测试和调试,但并未针对大规模生产运行进行性能优化。
KISS FFT 库包含在 LAMMPS 发行版中。它可以跨所有平台移植。根据 FFT 的大小和使用的处理器数量,此处列出的其他库可能会更快。
但是,请注意,长程库仑学只是每个时间步 CPU 成本的一部分,FFT 只是长程库仑学的一部分,1d FFT 只是 FFT 成本的一部分(并行通信的成本可能很高)。使用 kspace_style pppm 命令时,这些计时的细目会在运行结束时打印到屏幕上。屏幕和日志文件输出页面提供了更多详细信息。使用 kspace_modify fftbench yes 命令生成更详细(且耗时)的 FFT 性能报告。
FFTW 是一个快速、可移植的 FFT 库,它还可以在任何平台上工作,并且比 KISS FFT 库更快。您可以从 www.fftw.org 下载它。 LAMMPS 需要 3.X 版本;不再支持旧版本 2.1.X。
为您的盒子构建 FFTW 应该像 ./configure; make; make install
一样简单。安装命令通常需要 root 权限(例如通过 sudo 调用它),除非您使用配置的"--prefix"选项指定本地目录。输入 ./configure --help
查看各种选项。
英特尔 MKL 数学库是英特尔编译器套件的一部分。它可以与 Intel 或 GNU 编译器一起使用(请参阅上面的 FFT_LIB
设置)。
cuFFT 和 hipFFT FFT 库分别与 NVIDIA 的 CUDA 和 AMD 的 HIP 安装打包在一起。这些 FFT 库需要启用 Kokkos 加速包,并且 Kokkos 后端驻留在 GPU 上(即 HIP 或 CUDA)。
由于数据访问和所需的通信,并行执行 3d FFT 可能非常耗时。通过执行单精度 FFT 而不是双精度可以降低此成本。单精度意味着复数数据的实部和虚部是 4 字节浮点数。双精度意味着它们是 8 字节双精度数。请注意,傅里叶变换和相关的 PPPM 运算对浮点截断误差不太敏感,因此产生的误差通常小于精度差异。使用 -DFFT_SINGLE
设置会牺牲一点精度,以减少内存使用和转置 3d FFT 数据的并行通信成本。
将 -DFFT_SINGLE
与 FFTW3 一起使用时,您可能需要确保 FFTW3 安装包含对单精度的支持。
当从源代码编译 FFTW3 时,您可以执行以下操作,这应该生成附加库 libfftw3f.a
和/或 libfftw3f.so
。
make clean
./configure --enable-single; make; make install
执行 3d FFT 需要通信来转置 3d FFT 网格。为此的数据打包/解包可以通过上述 FFT_PACK 语法设置的 3 种模式(ARRAY、POINTER、MEMCPY)之一来完成。根据机器、FFT 网格的大小、使用的处理器数量,一种选择可能会稍微快一些。默认为 ARRAY 模式。
使用 -DFFT_HEFFTE
时,CMake 将首先按照 CMake 标准的建议使用 -DHeffte_ROOT
提供的提示查找现有安装,并注意名称区分大小写。如果 CMake 找不到具有正确后端(例如 FFTW 或 MKL)的 heFFTe 安装,它将尝试自动下载并构建库。在这种情况下,LAMMPS CMake 还将接受 heFFTe 文档中列出的所有 heFFTe 特定变量,并且这些变量将传递到 heFFTe 构建中。
3.5.3. LAMMPS 整数数据类型的大小和大小限制
LAMMPS 使用一些自定义整数数据类型,可以在编译时将其定义为 4 字节(= 32 位)或 8 字节(= 64 位)整数。这会影响可模拟系统的大小,或者"翻转"之前计数器可以变成多大。默认设置"smallbig"几乎总是足够的。
CMake构建
使用 CMake,可以通过在配置期间设置变量来选择整数类型。
-D LAMMPS_SIZES=value # smallbig (default) or bigbig or smallsmall
如果未显式设置该变量,则使用"smallbig"。
传统make
如果您想要与默认值不同的设置,则需要编辑机器 Makefile 的 LMP_INC
变量设置。
LMP_INC = -DLAMMPS_SMALLBIG # or -DLAMMPS_BIGBIG or -DLAMMPS_SMALLSMALL
如果未指定任何内容,则默认设置为 -DLAMMPS_SMALLBIG
LAMMPS 系统尺寸限制
"bigbig"设置比"smallbig"增加了图像标志和原子 ID 的大小,并且仅当您的计算机不支持 64 位整数或在使用它们时会导致性能损失时才需要"smallsmall"设置。
这些是 LAMMPS 代码核心的限制,特定功能或某些样式可能会施加额外的限制。 ATC 包无法使用"bigbig"设置进行编译。此外,使用库接口时也存在一些限制,其中一些存在已知问题的函数已被打印相应错误消息的虚拟调用所取代,而不是随机崩溃或损坏数据。
对于不存储键拓扑信息的原子系统,不需要原子 ID,尽管默认情况下启用 ID。 atom_modify id no 命令将关闭它们。具有键拓扑(键、角、二面体等)的分子系统需要原子 ID。同样,某些强制或计算或修复样式需要原子 ID。因此,如果您对分子系统进行建模或使用其中一种具有超过 20 亿个原子的样式,则需要"bigbig"设置。
无论总系统大小限制如何,每个 MPI 等级的最大原子数(本地 + 幽灵原子)对于原子系统限制为 20 亿,对于具有键的系统限制为 5 亿(附加限制是由于使用了 2 个高位)用于存储特殊键信息的邻居列表中的本地原子索引)。
图像标志在单个整数中为每个原子存储 3 个值,这些值计算原子在每个维度中穿过周期框的次数。请参阅转储手册页进行讨论。如果原子在周期盒中的移动超过此限制,则该值将"翻转",例如从 511 到 -512,这可能会导致由compute msd 命令计算的均方位移等诊断出现错误。
另请注意,GPU 包要求其 lib/gpu 库以相同的大小设置进行编译,否则链接将失败。 CMake 构建会自动执行此操作。使用 make 构建时,使用的 lib/gpu/Makefile
中的设置必须与上面相同。
3.5.4. JPG、PNG 和电影文件的输出
dump image 命令具有输出 JPEG 或 PNG 图像文件的选项。同样,dump movie 命令以各种电影格式输出电影文件。使用这些选项需要进行以下设置:
CMake构建
-D WITH_JPEG=value # yes or no
# default = yes if CMake finds JPEG files, else no
-D WITH_PNG=value # yes or no
# default = yes if CMake finds PNG and ZLIB files, else no
-D WITH_FFMPEG=value # yes or no
# default = yes if CMake can find ffmpeg, else no
通常这些设置就足够了。如果CMake找不到图形头、库、可执行文件,可以设置这些变量:
-D JPEG_INCLUDE_DIR=path # path to jpeglib.h header file
-D JPEG_LIBRARY=path # path to libjpeg.a (.so) file
-D PNG_INCLUDE_DIR=path # path to png.h header file
-D PNG_LIBRARY=path # path to libpng.a (.so) file
-D ZLIB_INCLUDE_DIR=path # path to zlib.h header file
-D ZLIB_LIBRARY=path # path to libz.a (.so) file
-D FFMPEG_EXECUTABLE=path # path to ffmpeg executable
传统make
LMP_INC = -DLAMMPS_JPEG -DLAMMPS_PNG -DLAMMPS_FFMPEG <other LMP_INC settings>
JPG_INC = -I/usr/local/include # path to jpeglib.h, png.h, zlib.h header files if make cannot find them
JPG_PATH = -L/usr/lib # paths to libjpeg.a, libpng.a, libz.a (.so) files if make cannot find them
JPG_LIB = -ljpeg -lpng -lz # library names
与 CMake 一样,如果 make 可以在默认系统位置找到图形头文件和库文件,则无需设置 JPG_INC
或 JPG_PATH
。您必须指定 JPG_LIB
以及要包含在链接中的图形库列表。您必须确保 ffmpeg 可执行文件(或 Windows 上的 ffmpeg.exe)位于 LAMMPS 在运行时可以找到它的目录中;这通常是 PATH
环境变量中的目录列表。
使用 ffmpeg
输出电影文件需要您的机器支持标准运行库中的"popen"函数。
注:在某些具有高速网络的集群上,使用 fork() 库调用(popen() 需要)可能会干扰快速通信库,并导致使用 ffmpeg 进行的模拟挂起或崩溃。
3.5.4. 读取或写入压缩文件
如果启用此选项,则可以通过 gzip
或类似工具通过多个 LAMMPS 命令(包括 read_data、rerun 和 dump)以压缩方式读取或写入大文件。目前支持的压缩工具有 gzip
、 bzip2
、 zstd
和 lzma
。
CMake构建
-D WITH_GZIP=value # yes or no
# default is yes if CMake can find the gzip program, else no
传统make
LMP_INC = -DLAMMPS_GZIP <other LMP_INC settings>
此选项要求您的操作系统完全支持标准运行时库中的"popen()"函数,并且在运行期间 LAMMPS 可以在标准搜索路径中找到 gzip
或其他可执行文件。
注:在具有高速网络的集群上,使用"fork()"库调用("popen()"所需)可能会干扰快速通信库,并导致使用压缩输出或输入的模拟挂起或崩溃。对于选定的操作,还可以使用压缩库来使用压缩文件 I/O,这正是 COMPRESS 包所支持的。
3.5.6.内存分配对齐
当 LAMMPS 分配大块内存时,此设置允许使用"posix_memalign()"调用而不是"malloc()"。如果动态分配的内存在大于默认字节边界上对齐,CPU 上的向量指令可能会变得更加高效。在大多数当前操作系统上,"malloc()"实现返回与 16 字节边界对齐的指针。然而,有效使用 SSE 向量指令需要内存块在 64 字节边界上对齐。
CMake构建
-D LAMMPS_MEMALIGN=value # 0, 8, 16, 32, 64 (default)
使用 LAMMPS_MEMALIGN
值 0 禁用"posix_memalign()"并恢复使用"malloc()"C 库函数。当为 Windows 系统编译 LAMMPS 时,将始终使用"malloc()"并且忽略此设置。
传统make
LMP_INC = -DLAMMPS_MEMALIGN=value # 8, 16, 32, 64
如果您想通过"malloc()"函数调用分配内存,请不要设置 -DLAMMPS_MEMALIGN
。 -DLAMMPS_MEMALIGN
不能在 Windows 上使用,因为 Windows 不同的函数调用具有不同的语义来分配对齐内存,这与 LAMMPS 管理其动态内存的方式不兼容。
3.5.7.长整型的解决方法
如果您的系统或 MPI 版本无法识别"long long"数据类型,则需要进行以下设置。它将"long long"转换为"long"数据类型,这应该是这些系统上所需的 8 字节整数:
CMake构建
-D LAMMPS_LONGLONG_TO_LONG=value # yes or no (default)
传统make
LMP_INC = -DLAMMPS_LONGLONG_TO_LONG <other LMP_INC settings>
3.5.8.使用 LAMMPS 作为库时的异常处理
LAMMPS 错误不会终止调用代码,但会引发异常。在 C 库接口中,调用堆栈被展开,控制权返回给调用者,例如Python 或与 LAMMPS 耦合的代码。然后可以查询错误状态。直接使用 C++ 时,必须设置调用代码以捕获从 LAMMPS 内部抛出的异常。
注:当 LAMMPS 并行运行时,并不总是能够从异常中干净地恢复,因为并非所有并行队列都可能抛出异常,因此其他 MPI 队列可能会陷入等待来自错误队列的消息。
3.5.9.触发选定的浮点异常
许多类型的 CPU 都能够检测计算何时导致无效的数学运算,例如除以零或使用负参数调用平方根。大多数操作系统上的默认行为是继续并具有 NaN
(= 非数字)或 Inf
(= 无穷大)值。这使得软件能够检测到此类情况并从中恢复。但是,通常可以通过使用编译器标志来更改此行为。在 Linux 系统上(或者更一般地在使用 GNU C 库的系统上),这些所谓的浮点陷阱也可以通过库调用有选择地启用。 LAMMPS 通过设置 -DLAMMPS_TRAP_FPE
预处理器定义来支持这一点。由于它是在 main()
函数中完成的,因此这仅适用于独立可执行文件,而不适用于库。
CMake构建
-D CMAKE_TUNE_FLAGS=-DLAMMPS_TRAP_FPE
传统make
LMP_INC = -DLAMMPS_TRAP_FPE <other LMP_INC settings>
设置此标志进行编译后,当遇到除零、溢出、非法数学函数参数或其他无效浮点运算时,LAMMPS 可执行文件将停止并生成核心转储。