Skip to content

Commit 3eec8d7

Browse files
committed
Restore setNumOMPthreads in the GROMACS 2025 patch (plumed#1435)
* Restore setNumOMPthreads in the GROMACS 2025 patch Up to the 2024.3 patch, PLUMED was told how many OpenMP threads GROMACS was using: int nth = gmx_omp_nthreads_get(ModuleMultiThread::Default); plumed_cmd(plumedmain, "setNumOMPthreads", &nth); When the 2025.0 patch was written against the native PLUMED support that GROMACS now ships, that call was not carried over. As a result PLMD::OpenMP::getNumThreads() always returns 1, and actions that parallelise over OpenMP silently run serially unless the user sets PLUMED_NUM_THREADS by hand -- which is not something that can be known in advance on a heterogeneous machine, nor after GROMACS' dynamic load balancing has redistributed the work. Reinstate the call in the PlumedForceProvider constructor, behind the same API-version gate the 2024.3 patch used. The value is available at that point: gmx_omp_nthreads_init() is called in runner.cpp well before the force providers are constructed. Fixes plumed#1407 * regtest: check that setNumOMPthreads reaches OpenMP::getNumThreads The patch this branch restores works by having the MD code tell PLUMED how many OpenMP threads it is using, via cmd("setNumOMPthreads"), from the PlumedForceProvider constructor. Nothing was covering that path. It cannot be covered from the patch side: patches/ is never compiled by PLUMED's build (no object is produced under it), and there is no harness that patches and builds a GROMACS tree. What can be covered, and is what actually broke, is the mechanism the patch depends on -- that the command is honoured and is visible to OpenMP::getNumThreads(). When it is not, getNumThreads() reports 1 and every OpenMP-parallel action silently runs serially: results stay correct, so only a test like this notices. Setting the value twice also pins down that the command is re-issuable rather than latch-once, and 0 is checked because PlumedMain maps it to 1 instead of passing a meaningless thread count through. The expected values are fixed (3, 5, 1) rather than machine-dependent: OpenMP::setNumThreads stores what it is given without clamping.
1 parent d26ee82 commit 3eec8d7

5 files changed

Lines changed: 53 additions & 0 deletions

File tree

patches/gromacs-2025.0.diff/src/gromacs/applied_forces/plumed/plumedforceprovider.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include "gromacs/domdec/domdec.h"
4545
#include "gromacs/domdec/domdec_struct.h"
4646
#include "gromacs/math/units.h"
47+
#include "gromacs/mdlib/gmx_omp_nthreads.h"
4748
#include "gromacs/mdrunutility/handlerestart.h"
4849
#include "gromacs/mdrunutility/multisim.h"
4950
#include "gromacs/mdtypes/commrec.h"
@@ -115,6 +116,15 @@ try : plumed_(std::make_unique<PLMD::Plumed>()),replex_(options.replex_)
115116
}
116117
}
117118

119+
if (plumedAPIversion_ > 5)
120+
{
121+
/* tell PLUMED how many OpenMP threads GROMACS is using, so that it can
122+
parallelise its own work; without this PLMD::OpenMP::getNumThreads()
123+
always reports 1 unless PLUMED_NUM_THREADS is set by hand */
124+
int numOmpThreads = gmx_omp_nthreads_get(ModuleMultiThread::Default);
125+
plumed_->cmd("setNumOMPthreads", &numOmpThreads);
126+
}
127+
118128
if (isMultiSim(options.ms_))
119129
{
120130
if (MAIN(options.cr_))
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include ../../scripts/test.make
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
type=make
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Checks the mechanism the MD-code patches rely on to tell PLUMED how many OpenMP threads the engine is
3+
* using: cmd("setNumOMPthreads") must be reflected by PLMD::OpenMP::getNumThreads().
4+
*
5+
* The GROMACS 2025 patch issues this command from the PlumedForceProvider constructor. Without it
6+
* getNumThreads() reports 1 and every OpenMP-parallel action silently runs serially, which is invisible
7+
* in results and only shows up as lost performance -- exactly the kind of regression a test should catch.
8+
*
9+
* Setting the value twice also pins down that the command is re-issuable rather than latch-once.
10+
*/
11+
#include "plumed/wrapper/Plumed.h"
12+
#include "plumed/tools/OpenMP.h"
13+
#include <fstream>
14+
15+
int main() {
16+
std::ofstream ofs("output");
17+
18+
// Query first so any PLUMED_NUM_THREADS in the environment has already been latched: the point is that
19+
// an explicit setNumOMPthreads overrides whatever the default resolved to.
20+
PLMD::OpenMP::getNumThreads();
21+
22+
PLMD::Plumed p;
23+
24+
unsigned nt = 3;
25+
p.cmd("setNumOMPthreads", &nt);
26+
ofs << "after setNumOMPthreads(3): " << PLMD::OpenMP::getNumThreads() << "\n";
27+
28+
nt = 5;
29+
p.cmd("setNumOMPthreads", &nt);
30+
ofs << "after setNumOMPthreads(5): " << PLMD::OpenMP::getNumThreads() << "\n";
31+
32+
// 0 threads is meaningless; PlumedMain maps it to 1 rather than passing it through.
33+
nt = 0;
34+
p.cmd("setNumOMPthreads", &nt);
35+
ofs << "after setNumOMPthreads(0): " << PLMD::OpenMP::getNumThreads() << "\n";
36+
37+
return 0;
38+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
after setNumOMPthreads(3): 3
2+
after setNumOMPthreads(5): 5
3+
after setNumOMPthreads(0): 1

0 commit comments

Comments
 (0)