diff --git a/doc/htmldoc/hpc/parallel_computing.rst b/doc/htmldoc/hpc/parallel_computing.rst
index 5746fc1970..93cfc0d4b9 100644
--- a/doc/htmldoc/hpc/parallel_computing.rst
+++ b/doc/htmldoc/hpc/parallel_computing.rst
@@ -188,12 +188,22 @@ command for this is
Usually, a good choice for `T` is the number of processor cores available
on your machine.
-.. note::
-
- In some situations, `oversubscribing` (i.e., to specify a ``local_num_threads`` that is higher than available cores on your machine)
- can yield 20-30% improvement in simulation speed. Finding the optimal thread number for a
- specific situation might require a bit of experimenting.
-
+In some situations, `oversubscribing` (i.e., to specify a
+``local_num_threads`` that is higher than available cores on your
+machine) can yield 20–30% improvement in simulation speed. Finding the
+optimal thread number for a specific situation might require a bit of
+experimenting.
+
+.. admonition:: NEST ignores OMP_NUM_THREADS
+
+ NEST ignores ``OMP_NUM_THREADS`` environment
+ variable, which may be set by mpi4py, Slurm or similar runtime
+ environments. NEST will always start running on a single thread
+ until the number of threads is changed by setting either the
+ ``local_num_threads`` or the ``total_num_virtual_procs``
+ :ref:`kernel attribute`.
+
+
Multiprocessing
---------------
diff --git a/doc/htmldoc/ref_material/pynest_api/nest.NestModule.rst b/doc/htmldoc/ref_material/pynest_api/nest.NestModule.rst
index d175f1235d..f780fc7d4b 100644
--- a/doc/htmldoc/ref_material/pynest_api/nest.NestModule.rst
+++ b/doc/htmldoc/ref_material/pynest_api/nest.NestModule.rst
@@ -1,4 +1,4 @@
-.. _sec:kernel_attributes:
+.. _sec_kernel_attributes:
Kernel attributes (nest.NestModule)
===================================
diff --git a/nestkernel/vp_manager.cpp b/nestkernel/vp_manager.cpp
index af62ca08c2..cf75afdf56 100644
--- a/nestkernel/vp_manager.cpp
+++ b/nestkernel/vp_manager.cpp
@@ -60,6 +60,15 @@ nest::VPManager::initialize()
// of threads used for parallel regions.
omp_set_dynamic( false );
#endif
+
+ if ( get_OMP_NUM_THREADS() > 1 )
+ {
+ std::string msg = "OMP_NUM_THREADS is set in your environment, but NEST ignores it.\n";
+ msg += "For details, see the Guide to parallel computing in the NEST Documentation.";
+
+ LOG( M_INFO, "VPManager::initialize()", msg );
+ }
+
set_num_threads( 1 );
}
@@ -68,6 +77,20 @@ nest::VPManager::finalize()
{
}
+size_t
+nest::VPManager::get_OMP_NUM_THREADS() const
+{
+ const char* const omp_num_threads = std::getenv( "OMP_NUM_THREADS" );
+ if ( omp_num_threads )
+ {
+ return std::atoi( omp_num_threads );
+ }
+ else
+ {
+ return 0;
+ }
+}
+
void
nest::VPManager::set_status( const DictionaryDatum& d )
{
@@ -95,22 +118,12 @@ nest::VPManager::set_status( const DictionaryDatum& d )
}
}
- if ( force_singlethreading_ and n_threads > 1 )
- {
- throw BadProperty( "This installation of NEST was built without support for multiple threads." );
- }
-
// We only want to act if new values differ from the old
n_threads_updated = n_threads != get_num_threads();
n_vps_updated = n_vps != get_num_virtual_processes();
if ( n_threads_updated or n_vps_updated )
{
- if ( kernel().sp_manager.is_structural_plasticity_enabled() and n_threads > 1 )
- {
- throw KernelException( "Structural plasticity enabled: multithreading cannot be enabled." );
- }
-
std::vector< std::string > errors;
if ( kernel().node_manager.size() > 0 )
{
@@ -128,12 +141,16 @@ nest::VPManager::set_status( const DictionaryDatum& d )
{
errors.push_back( "Model defaults were modified" );
}
-
- if ( errors.size() == 1 )
+ if ( kernel().sp_manager.is_structural_plasticity_enabled() and n_threads > 1 )
{
- throw KernelException( errors[ 0 ] + ": number of threads cannot be changed." );
+ errors.push_back( "Structural plasticity enabled: multithreading cannot be enabled" );
}
- if ( errors.size() > 1 )
+ if ( force_singlethreading_ and n_threads > 1 )
+ {
+ errors.push_back( "This installation of NEST does not support for multiple threads" );
+ }
+
+ if ( not errors.empty() )
{
std::string msg = "Number of threads unchanged. Error conditions:";
for ( auto& error : errors )
@@ -143,6 +160,13 @@ nest::VPManager::set_status( const DictionaryDatum& d )
throw KernelException( msg );
}
+ if ( get_OMP_NUM_THREADS() > 0 and get_OMP_NUM_THREADS() != n_threads )
+ {
+ std::string msg = "OMP_NUM_THREADS is set in your environment, but NEST ignores it.\n";
+ msg += "For details, see the Guide to parallel computing in the NEST Documentation.";
+ LOG( M_WARNING, "VPManager::set_status()", msg );
+ }
+
kernel().change_number_of_threads( n_threads );
}
}
@@ -157,23 +181,7 @@ nest::VPManager::get_status( DictionaryDatum& d )
void
nest::VPManager::set_num_threads( size_t n_threads )
{
- if ( kernel().sp_manager.is_structural_plasticity_enabled() and n_threads > 1 )
- {
- throw KernelException( "Multiple threads can not be used if structural plasticity is enabled" );
- }
-
- char* omp_num_threads = std::getenv( "OMP_NUM_THREADS" );
- if ( omp_num_threads and static_cast< size_t >( std::atoi( omp_num_threads ) ) != n_threads )
- {
- const std::string tstr = ( n_threads > 1 ) ? "threads" : "thread";
- const int ONT = std::atoi( omp_num_threads );
- std::string msg = "The new number of threads disagrees with the environment variable OMP_NUM_THREADS.\n";
- msg += "NEST only respects the kernel attributes /local_num_threads or /total_num_virtual_procs\n";
- msg += String::compose( "and will now use %1 %2 and ignore OMP_NUM_THREADS (set to %3).", n_threads, tstr, ONT );
-
- LOG( M_WARNING, "MPIManager::init_mpi()", msg );
- }
-
+ assert( not( kernel().sp_manager.is_structural_plasticity_enabled() and n_threads > 1 ) );
n_threads_ = n_threads;
#ifdef _OPENMP
diff --git a/nestkernel/vp_manager.h b/nestkernel/vp_manager.h
index 5362779e3d..b862d75cce 100644
--- a/nestkernel/vp_manager.h
+++ b/nestkernel/vp_manager.h
@@ -83,6 +83,13 @@ class VPManager : public ManagerInterface
*/
size_t get_num_threads() const;
+ /**
+ * Get OMP_NUM_THREADS environment variable.
+ *
+ * @note Returns 0 if OMP_NUM_THREADS is not set.
+ */
+ size_t get_OMP_NUM_THREADS() const;
+
/**
* Returns true if the given global node exists on this vp.
*/