很多人在服务器上配置了昂贵的 A100 或是最新的 RTX 4090 显卡,但在运行 GROMACS 模拟时,却发现 GPU 占用率长期在 30% 到 50% 之间徘徊,跑出来的 ns/day 数据甚至不如低端显卡。
这种现象大概率不是硬件故障,而是直接套用了多年前针对纯 CPU 平台设计的 .mdp 模板。在现代 GROMACS(特别是 2020 及更高版本)中,GPU 不仅负责计算非键相互作用(Non-bonded forces),还可以接管 PME(倒易空间静电)、Update(坐标更新和约束)。
一旦 MDP 参数设置不当,就会导致频繁的 CPU-GPU 数据拷贝(PCIe 瓶颈)或任务串行等待。以下是几个对 GPU 计算效率影响最致命的 MDP 参数,以及优化这些参数的具体建议。
1. 邻居列表更新频率:nstlist 与 cutoff-scheme
这是影响 GPU 性能最核心的参数之一。
cutoff-scheme = Verlet
nstlist = 40 ; 严禁在使用 GPU 时将其设为 10 或 20
cutoff-scheme必须为Verlet:传统的Group方案不仅早已被官方废弃,而且根本无法在 GPU 上高效运行。nstlist必须调大:在纯 CPU 时代,大家习惯将nstlist设为 10 或 20。但在 GPU 加速模拟中,重新构建邻居表(Neighbor Searching)是在 CPU 上完成的(或者需要 CPU-GPU 强同步)。如果nstlist设得太小,CPU 就会频繁介入,导致 GPU 每隔十几步就要停下来等待 CPU 算完邻居表,造成严重的显卡饥饿。- 优化策略:在使用 GPU 跑 PME 时,建议将
nstlist设为 40 到 80。GROMACS 具有动态缓冲(Verlet buffer tolerance)机制,它会自动根据你设定的nstlist和verlet-buffer-tolerance = 0.005(默认值)来微调实际的截断半径,保证物理精度不受影响。因此,大胆地把nstlist设为 40 甚至更高,能够显著释放 GPU 的计算连续性。
2. 极易被忽视的显卡杀手:I/O 写入频率
这是新手最容易踩的坑。许多人为了获得高精度的轨迹,把能量和轨迹写入频率设得极高。
nstxout = 0 ; 关闭未压缩轨迹写入(*.trr)
nstvout = 0
nstfout = 0
nstxout-compressed= 50000 ; 压缩轨迹(*.xtc)写入步数
nstenergy = 50000 ; 能量写入步数
nstlog = 50000 ; 日志写入步数
- 瓶颈本质:GPU 在计算时,所有的坐标、速度、力信息都存储在显存中。一旦到了触发写入(如
nstenergy或nstxout)的那一步,GROMACS 必须将显存中的数据通过 PCIe 总线拉回到系统内存(CPU),然后由 CPU 格式化并写入硬盘。 - 性能损耗:如果你把
nstenergy设为100或1000,意味着每过几皮秒,GPU 就要被迫中断计算,进行一次昂贵的数据同步。这会产生巨大的 I/O 阻塞。 - 优化策略:除非你在进行高频的数据采样(如某些自由能计算或特定拉伸模拟),否则请将
nstxout-compressed、nstenergy和nstlog至少设为 10000 到 50000。日常平衡和生产跑不建议保留未压缩的*.trr坐标和速度输出(全设为 0)。
3. 约束算法与 GPU 更新的核心:constraints
从 GROMACS 2020 开始,支持将坐标更新(Update)和约束(Constraints)完全放到 GPU 上运行(通过命令行参数 -update gpu 开启)。
要顺利开启此功能,MDP 中的约束设置必须满足 GPU 的硬性要求:
constraints = h-bonds ; 或者是 all-bonds
constraint-algorithm = LINCS ; 严禁在 GPU update 时使用 SHAKE
lincs-order = 4
lincs-iter = 1
- 为什么不能用 SHAKE:GROMACS 的 GPU Update 模块目前只支持 LINCS 算法。如果你的 MDP 中写了
constraint-algorithm = SHAKE,GROMACS 将无法把 Update 步骤移至 GPU,被迫在每一步迭代中把力数据传回 CPU 计算约束,再把新坐标传回 GPU。这种高频的双向数据拷贝会彻底击碎 GPU 的算力优势。 - 优化策略:确保使用
LINCS约束。对于含有氢原子的体系,通常设置constraints = h-bonds配合 2 fs 的步长。
4. 倒易空间静电与范德华力截断:rcoulomb 与 rvdw
coulombtype = PME
rcoulomb = 1.0 ; 适当调整,为 CPU/GPU 负载均衡留出空间
rvdw = 1.0
在使用 GPU 跑 PME 时,GROMACS 会在实空间(Real space)计算和倒易空间(Reciprocal space/PME)计算之间分配任务。
- 参数关联:
rcoulomb(库仑力截断半径)的大小决定了实空间和倒易空间的工作量分配。 - 如果你的 GPU 极强(如 H100/RTX 4090)而 CPU 较弱,你可能需要将 PME 完全放到 GPU 上(
gmx mdrun -nb gpu -pme gpu)。此时,可以适当通过gmx mdrun -tunepme开启自动调节,它会在运行初期动态测试不同的rcoulomb距离,把最适合的计算比例交由 GPU 处理。 - 一般情况下,保持
rcoulomb = rvdw = 1.0或者是1.2即可,不要随意设置奇奇怪怪的非对称截断(例如rcoulomb = 0.9配合rvdw = 1.2),这会增加 GPU 的分支预测开销。
5. 控温与控压算法:tcoupl 与 pcoupl
虽然控温控压本身计算量不大,但不同的算法在 GPU 上的兼容性和同步开销不同。
tcoupl = v-rescale ; 推荐
pcoupl = c-rescale ; GROMACS 2021+ 推荐
; pcoupl = Parrinello-Rahman
- 温度耦合:
v-rescale(Velocity Rescaling)是极度推荐的算法。它不仅在物理上给出了正确的正则系综,而且在数值上极其稳定,与 GPU 加速的集成契合度极高。相比之下,Nose-Hoover稍微复杂一些,虽然也支持,但在一些老版本 GPU 代码中可能存在极小的额外开销。 - 压力耦合:传统的
Parrinello-Rahman算法由于计算波动较大,容易在模拟初期导致体系不稳定。而在较新版的 GROMACS 中,官方引入了c-rescale(Stochastic cell rescaling),它比Parrinello-Rahman更鲁棒,且非常适合在 GPU 加速下稳定快速地进行 NPT 平衡。
避坑 checklist:一份 GPU 友好的高效生产 MDP 配置片段
如果你的目标是榨干显卡性能,请对照修改你的 .mdp 文件:
; 积分器与步长
integrator = md
dt = 0.002
nsteps = 50000000 ; 100 ns
; 邻居表与截断(GPU 核心优化)
cutoff-scheme = Verlet
nstlist = 40
verlet-buffer-tolerance = 0.005
ns-type = grid
; 静电与范德华
coulombtype = PME
rcoulomb = 1.0
vdwtype = Cut-off
rvdw = 1.0
DispCorr = EnerPres
; 极简 I/O 减少数据回传
nstxout = 0
nstvout = 0
nstfout = 0
nstlog = 50000
nstenergy = 50000
nstxout-compressed = 50000
; 约束(允许 -update gpu)
constraints = h-bonds
constraint-algorithm = LINCS
lincs-order = 4
lincs-iter = 1
最后,有了完美的 .mdp 文件,启动命令也必须配合好。例如对于单卡 NVIDIA 平台,推荐使用如下命令启动:
gmx mdrun -v -deffnm prod -nb gpu -pme gpu -update gpu
这里的 -update gpu 会强制把坐标更新和约束也留在显存中进行。此时你会发现,GPU 占用率终于飚了上去,而每日模拟纳秒数(ns/day)也迎来了质的飞跃。