笔者在进行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。 -
每次测试使用命令:
bashgmx 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 技术白皮书