/* The options for the thread affinity setting, default: auto */
-enum {
- threadaffSEL, threadaffAUTO, threadaffON, threadaffOFF, threadaffNR
+enum class ThreadAffinity
+{
+ Select,
+ Auto,
+ On,
+ Off,
+ Count
};
/*! \internal \brief Threading and GPU options, can be set automatically or by the user
struct gmx_hw_opt_t
{
//! Total number of threads requested (thread-MPI + OpenMP).
- int nthreads_tot = 0;
+ int nthreads_tot = 0;
//! Number of thread-MPI threads requested.
- int nthreads_tmpi = 0;
+ int nthreads_tmpi = 0;
//! Number of OpenMP threads requested.
- int nthreads_omp = 0;
+ int nthreads_omp = 0;
//! Number of OpenMP threads to use on PME_only ranks.
- int nthreads_omp_pme = 0;
+ int nthreads_omp_pme = 0;
//! Thread affinity switch, see enum above.
- int thread_affinity = threadaffSEL;
+ ThreadAffinity threadAffinity = ThreadAffinity::Select;
//! Logical core pinning stride.
- int core_pinning_stride = 0;
+ int core_pinning_stride = 0;
//! Logical core pinning offset.
- int core_pinning_offset = 0;
+ int core_pinning_offset = 0;
//! Empty, or a string provided by the user declaring (unique) GPU IDs available for mdrun to use.
- std::string gpuIdsAvailable = "";
+ std::string gpuIdsAvailable = "";
//! Empty, or a string provided by the user mapping GPU tasks to devices.
- std::string userGpuTaskAssignment = "";
+ std::string userGpuTaskAssignment = "";
//! Tells whether mdrun is free to choose the total number of threads (by choosing the number of OpenMP and/or thread-MPI threads).
- bool totNumThreadsIsAuto;
+ bool totNumThreadsIsAuto;
};
#endif
}
}
- hw_opt.thread_affinity = nenum(thread_aff_opt_choices);
+ hw_opt.threadAffinity = static_cast<ThreadAffinity>(nenum(thread_aff_opt_choices));
// now check for a multi-simulation
ArrayRef<const std::string> multidir = opt2fnsIfOptionSet("-multidir",
{ nullptr, "interleave", "pp_pme", "cartesian", nullptr };
const char *dddlb_opt_choices[static_cast<int>(DlbOption::Count)+1] =
{ nullptr, "auto", "no", "yes", nullptr };
- const char *thread_aff_opt_choices[threadaffNR+1] =
+ const char *thread_aff_opt_choices[static_cast<int>(ThreadAffinity::Count) + 1] =
{ nullptr, "auto", "on", "off", nullptr };
const char *nbpu_opt_choices[5] =
{ nullptr, "auto", "cpu", "gpu", nullptr };
*hwinfo->hardwareTopology,
physicalNodeComm, mdlog);
- if (hw_opt.thread_affinity != threadaffOFF)
+ if (hw_opt.threadAffinity != ThreadAffinity::Off)
{
/* Before setting affinity, check whether the affinity has changed
* - which indicates that probably the OpenMP library has changed it
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2019, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
TEST_F(ThreadAffinityTest, DoesNothingWhenDisabled)
{
- helper_.setAffinityOption(threadaffOFF);
+ helper_.setAffinityOption(ThreadAffinity::Off);
helper_.setAffinity(1);
}
TEST_F(ThreadAffinityTest, DoesNothingWithUnknownHardware)
{
- helper_.setAffinityOption(threadaffON);
+ helper_.setAffinityOption(ThreadAffinity::On);
helper_.setLogicalProcessorCount(0);
helper_.expectWarningMatchingRegex("No information on available cores");
helper_.setAffinity(2);
TEST_F(ThreadAffinityTest, DoesNothingWithTooManyThreads)
{
- helper_.setAffinityOption(threadaffON);
+ helper_.setAffinityOption(ThreadAffinity::On);
helper_.setLogicalProcessorCount(4);
helper_.expectWarningMatchingRegex("Oversubscribing the CPU");
helper_.setAffinity(8);
TEST_F(ThreadAffinityTest, DoesNothingWithTooLargeOffset)
{
- helper_.setAffinityOption(threadaffON);
+ helper_.setAffinityOption(ThreadAffinity::On);
helper_.setOffsetAndStride(2, 0);
helper_.setLogicalProcessorCount(4);
helper_.expectWarningMatchingRegex("Applying core pinning offset 2");
TEST_F(ThreadAffinityTest, DoesNothingWithTooLargeStride)
{
- helper_.setAffinityOption(threadaffON);
+ helper_.setAffinityOption(ThreadAffinity::On);
helper_.setOffsetAndStride(0, 2);
helper_.setLogicalProcessorCount(4);
helper_.expectWarningMatchingRegex("Requested stride too large");
TEST_F(ThreadAffinityTest, PinsSingleThreadWhenForced)
{
- helper_.setAffinityOption(threadaffON);
+ helper_.setAffinityOption(ThreadAffinity::On);
helper_.setLogicalProcessorCount(2);
helper_.expectPinningMessage(false, 2);
helper_.expectAffinitySet(0);
TEST_F(ThreadAffinityTest, PinsSingleThreadWithOffsetWhenForced)
{
- helper_.setAffinityOption(threadaffON);
+ helper_.setAffinityOption(ThreadAffinity::On);
helper_.setOffsetAndStride(2, 0);
helper_.setLogicalProcessorCount(4);
helper_.expectWarningMatchingRegex("Applying core pinning offset 2");
TEST_F(ThreadAffinityTest, PinsMultipleThreadsWithStrideWhenForced)
{
- helper_.setAffinityOption(threadaffON);
+ helper_.setAffinityOption(ThreadAffinity::On);
helper_.setOffsetAndStride(0, 2);
helper_.setLogicalProcessorCount(4);
helper_.expectPinningMessage(true, 2);
TEST_F(ThreadAffinityTest, HandlesPinningFailureWithOneThreadFailing)
{
- helper_.setAffinityOption(threadaffON);
+ helper_.setAffinityOption(ThreadAffinity::On);
helper_.setLogicalProcessorCount(2);
helper_.expectPinningMessage(false, 1);
helper_.expectGenericFailureMessage();
{
GMX_MPI_TEST(4);
ThreadAffinityTestHelper helper;
- helper.setAffinityOption(threadaffON);
+ helper.setAffinityOption(ThreadAffinity::On);
helper.setOffsetAndStride(1, 2);
helper.setLogicalProcessorCount(8);
helper.expectWarningMatchingRegex("Applying core pinning offset 1");
{
GMX_MPI_TEST(4);
ThreadAffinityTestHelper helper;
- helper.setAffinityOption(threadaffOFF);
+ helper.setAffinityOption(ThreadAffinity::Off);
helper.setLogicalProcessorCount(4);
helper.setAffinity(1);
}
{
GMX_MPI_TEST(4);
ThreadAffinityTestHelper helper;
- helper.setAffinityOption(threadaffON);
+ helper.setAffinityOption(ThreadAffinity::On);
helper.setLogicalProcessorCount(6);
helper.expectWarningMatchingRegex("Oversubscribing the CPU");
helper.setAffinity(2);
{
GMX_MPI_TEST(4);
ThreadAffinityTestHelper helper;
- helper.setAffinityOption(threadaffON);
+ helper.setAffinityOption(ThreadAffinity::On);
setupNodes(&helper, {{2, 1}});
helper.expectWarningMatchingRegexIf("Oversubscribing the CPU", isMaster() || currentNode() == 1);
if (currentNode() == 0)
{
GMX_MPI_TEST(4);
ThreadAffinityTestHelper helper;
- helper.setAffinityOption(threadaffON);
+ helper.setAffinityOption(ThreadAffinity::On);
setupNodes(&helper, {{1, 2}});
helper.expectWarningMatchingRegexIf("Oversubscribing the CPU", currentNode() == 0);
if (currentNode() == 1)
{
GMX_MPI_TEST(4);
ThreadAffinityTestHelper helper;
- helper.setAffinityOption(threadaffON);
+ helper.setAffinityOption(ThreadAffinity::On);
setupNodes(&helper, {{2, 0}});
helper.expectWarningMatchingRegexIf("No information on available cores", isMaster() || currentNode() == 1);
if (currentNode() == 0)
{
GMX_MPI_TEST(4);
ThreadAffinityTestHelper helper;
- helper.setAffinityOption(threadaffON);
+ helper.setAffinityOption(ThreadAffinity::On);
helper.setOffsetAndStride(2, 0);
setupNodes(&helper, {{4, 2}});
helper.expectWarningMatchingRegex("Applying core pinning offset 2");
{
GMX_MPI_TEST(4);
ThreadAffinityTestHelper helper;
- helper.setAffinityOption(threadaffON);
+ helper.setAffinityOption(ThreadAffinity::On);
helper.setOffsetAndStride(0, 2);
setupNodes(&helper, {{4, 2}});
helper.expectWarningMatchingRegexIf("Requested stride too large", isMaster() || currentNode() == 1);
#if GMX_MPI
cr_->mpi_comm_mysim = MPI_COMM_WORLD;
#endif
- hwOpt_.thread_affinity = threadaffAUTO;
+ hwOpt_.threadAffinity = ThreadAffinity::Auto;
hwOpt_.totNumThreadsIsAuto = false;
physicalNodeId_ = 0;
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2016,2017,2018, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017,2018,2019, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
{
affinityAccess_.setSupported(supported);
}
- void setAffinityOption(int affinityOption)
+ void setAffinityOption(ThreadAffinity affinityOption)
{
- hwOpt_.thread_affinity = affinityOption;
+ hwOpt_.threadAffinity = affinityOption;
}
void setOffsetAndStride(int offset, int stride)
{
{
int *localityOrder = nullptr;
- if (hw_opt->thread_affinity == threadaffOFF)
+ if (hw_opt->threadAffinity == ThreadAffinity::Off)
{
/* Nothing to do */
return;
}
bool affinityIsAutoAndNumThreadsIsNotAuto =
- (hw_opt->thread_affinity == threadaffAUTO &&
+ (hw_opt->threadAffinity == ThreadAffinity::Auto &&
!hw_opt->totNumThreadsIsAuto);
bool issuedWarning;
bool validLayout
* thread-MPI whether it should do pinning when spawning threads.
* TODO: the above no longer holds, we should move these checks later
*/
- if (hw_opt->thread_affinity != threadaffOFF)
+ if (hw_opt->threadAffinity != ThreadAffinity::Off)
{
char *message;
if (!gmx_omp_check_thread_affinity(&message))
{
/* We only pin automatically with totNumThreadsIsAuto=true */
- if (hw_opt->thread_affinity == threadaffON ||
+ if (hw_opt->threadAffinity == ThreadAffinity::On ||
hw_opt->totNumThreadsIsAuto)
{
GMX_LOG(mdlog.warning).asParagraph().appendText(message);
}
sfree(message);
- hw_opt->thread_affinity = threadaffOFF;
+ hw_opt->threadAffinity = ThreadAffinity::Off;
}
}
}
if (!detectDefaultAffinityMask(nthreads_hw_avail))
{
- if (hw_opt->thread_affinity == threadaffAUTO)
+ if (hw_opt->threadAffinity == ThreadAffinity::Auto)
{
if (!bAfterOpenmpInit)
{
"Non-default thread affinity set probably by the OpenMP library,\n"
"disabling internal thread affinity");
}
- hw_opt->thread_affinity = threadaffOFF;
+ hw_opt->threadAffinity = ThreadAffinity::Off;
}
else
{