[Gromacs]核心性能梯度测试:GROMACS 多线程性能调优实验
笔者在进行Gromacs动力学模拟时发现,当我们将线程数设置成最大CPU线程数时,性能反而不如减少25%线程时候性能高,大概率是线程过高通信开销过大,因此设计了这个实验来验证笔者的想法与寻找最优线程数。分子动力学(MD)模拟中,我们需要设置并行线程数对计算效率非常重要。我们实验在一台配备 AMD Threadripper PRO 5945WX(12 物理核心,24 逻辑核心)和 NVIDIA RTX 4090 GPU 的工作站上,测试了 GROMACS 2024.6 在不同 OpenMP 线程数(10~24)下进行5000Steps模拟。但是结果显示,整体性能波动小于 3%,最佳的性能出现在 22 线程(480.1 ns/day),但 12 线程(物理核心数)的性能(475.9 ns/day)与之几乎持平,而 24 线程(全逻辑核心)并未没有带来进一步提升,甚至略低于 12 线程。我们从超线程技术、GROMACS 并行、GPU 加速负载分配、内存带宽和线程开销等角度深入分析,为类似平台的 MD 模拟参数优化提供一些参考。
1. Gromacs 线程概要
GROMACS 支持 MPI 和 OpenMP 混合并行,并能利用 GPU 加速非键相互作用和 PME 计算。在实际运行中,用户常通过 -ntmpi 和 -ntomp 手动指定 MPI 进程数和 OpenMP 线程数,以期获得最佳性能。然而,默认的自动设置往往并不总是最优,尤其当系统同时启用超线程(SMT)时,使用全部逻辑核心(如 24 线程)可能并不比使用物理核心数(12 线程)更快,甚至出现性能下降。
我们记录了在固定体系(蛋白-配体复合物,约 40891 个原子)下,不同 OpenMP 线程数对 GROMACS 性能的影响,并结合硬件架构和软件并行机制,解释为什么“线程越多不一定越快”。
2. 实验环境
2.1 硬件配置
| 组件 | 型号/规格 |
|---|---|
| CPU | AMD Ryzen Threadripper PRO 5945WX 12 核 24 线程 |
| 物理核心 | 12 |
| 逻辑核心 | 24(超线程开启,每核心 2 线程) |
| GPU | NVIDIA GeForce RTX 4090 (24 GB) |

2.2 软件版本
- GROMACS 2024.6(单精度,GPU 加速编译)
- CUDA 12.4,NVIDIA 驱动 550.54.14

2.3 模拟体系
- 蛋白-配体复合物,溶剂为水,总原子数 40891。
- 模拟步长 2 fs,测试时运行 5000 步(10 ps)以获取性能数据。
3. 实验方法
- 使用
gmx grompp生成 MD 输入文件md.tpr。 - 保持 MPI 进程数为 1(
-ntmpi 1),依次设置 OpenMP 线程数(-ntomp)为 10, 11, 12, 13, 14, 16, 18, 20, 22, 24。 - 每次测试使用命令:
gmx mdrun -v -s md.tpr -deffnm md_nt${n} -ntmpi 1 -ntomp ${n} -pin on -nsteps 5000其中
-pin on用于将线程绑定到 CPU 核心,减少迁移开销。 - 每个线程数重复 3 次,记录 GROMACS 输出的性能指标(ns/day),计算平均值和标准差。
4. 实验结果
4.1 原始数据与统计
表 1 列出了三次重复测试的性能值及统计结果。
| ntomp | Run1 (ns/day) | Run2 (ns/day) | Run3 (ns/day) | 平均值 (ns/day) | 标准差 |
|---|---|---|---|---|---|
| 10 | 471.398 | 473.918 | 475.185 | 473.500 | 1.557 |
| 11 | 471.537 | 476.148 | 364.743* | 437.476 | 51.355 |
| 12 | 476.158 | 475.211 | 476.327 | 475.899 | 0.487 |
| 13 | 473.907 | 474.625 | 470.910 | 473.147 | 1.608 |
| 14 | 469.652 | 468.913 | 469.876 | 469.480 | 0.409 |
| 16 | 475.467 | 479.616 | 465.833 | 473.639 | 5.741 |
| 18 | 475.487 | 478.358 | 469.746 | 474.530 | 3.591 |
| 20 | 477.547 | 369.734* | 480.890 | 442.724 | 51.976 |
| 22 | 478.737 | 480.669 | 481.004 | 480.137 | 1.003 |
| 24 | 478.363 | 467.018 | 478.638 | 474.673 | 5.421 |
注:带 * 的数据明显偏离其他重复(如第二次的 20 线程 369.734,第三次的 11 线程 364.743),可能是系统后台负载波动所致,但未在统计中剔除。
4.2 性能曲线

从平均值看,性能整体平缓,最高点为 22 线程(480.137 ns/day),12 线程为 475.899 ns/day,24 线程为 474.673 ns/day。最大差异不足 3%,说明在该体系下,CPU 线程数的影响有限。
5. 为什么更多线程没有带来更快速度?
5.1 GPU 加速导致 CPU 负载不饱和
我们实验中,GROMACS 已将短程非键相互作用(PP)和 PME 计算完全卸载到 RTX 4090 上(日志显示 “PP tasks will do … on the GPU”,“PME tasks will do all aspects on the GPU”)。这意味着计算瓶颈主要在 GPU,CPU 只负责坐标更新、约束、邻居列表构建等轻量任务。当 GPU 成为性能瓶颈时,增加 CPU 线程数并不能缩短墙钟时间,因为 CPU 大多数时间在等待 GPU 完成工作。这与 Amdahl 定律一致:可并行部分占比越小,增加处理器数量带来的加速越有限。
5.2 超线程(SMT)的局限性
AMD 的超线程技术(SMT)允许每个物理核心同时执行两个线程,但这两个线程共享核心内的执行单元、缓存和内存带宽。当两个线程竞争同一资源时,性能提升通常只有 10%~30%,甚至可能因资源冲突而下降。对于 GROMACS 这类浮点密集型应用,物理核心的计算单元利用率已很高,启用超线程后,第二个线程往往只能利用闲置的整数单元或等待内存访问的间隙,无法提供线性加速。而且,线程切换还会引入额外开销。因此,使用超过物理核心数的线程(如 13~24)时,性能不会显著提升,甚至可能因调度和资源争用略有下降。
12 线程(物理核心数)与 22 线程的平均性能几乎相同(475.9 vs 480.1 ns/day),印证了这一点。24 线程略低于 22 线程,可能是由于所有逻辑核心均被占用,操作系统或 GROMACS 内部的线程管理开销增加。
5.3 线程同步与通信开销
随着线程数增加,GROMACS 内部的线程同步(如 barrier、归约操作)频率上升,尤其在域分解和 PME 网格通信阶段。虽然 MPI 进程数固定为 1,OpenMP 线程间的共享内存通信开销相对较小,但当线程数超过物理核心数时,线程可能在核心间频繁迁移(即使使用 -pin on,超线程的逻辑核心仍可能与物理核心配对),导致缓存局部性变差,增加延迟。
6. 结论与建议
本实验表明,在配备 12 物理核心 CPU 和高端 GPU 的工作站上,对于 ~40k 原子的 MD 体系,GROMACS 性能对 OpenMP 线程数不敏感。最佳性能出现在 22 线程(480 ns/day),但与 12 线程(476 ns/day)的差异不足 1%,处于测量误差范围内。使用全部 24 个逻辑核心并未带来进一步提升,尽量预留25%的线程核心空间,减小线程间的通信开销。
最后建议:
- 优先保证 GPU 利用率:在 GPU 加速的模拟中,CPU 线程数调整的收益很小,应确保 GPU 满载运行(如使用
-nb gpu -pme gpu)。 - 使用物理核心数作为起点:对于纯 CPU 模拟,建议设置
-ntomp为物理核心数,再根据测试微调。对于 GPU 模拟,可以尝试物理核心数或略高(如 12~18)即可,不要追求全部逻辑核心。 - 始终启用线程绑定:
-pin on可以减少线程迁移,改善性能稳定性。
参考文献
- GROMACS 官方文档:https://manual.gromacs.org/
- AMD SMT 技术白皮书


