LCOV - code coverage report
Current view: top level - tools - OpenMP.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 30 30 100.0 %
Date: 2026-11-12 10:48:31 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2014-2023 The plumed team
       3             :    (see the PEOPLE file at the root of the distribution for a list of names)
       4             : 
       5             :    See http://www.plumed.org for more information.
       6             : 
       7             :    This file is part of plumed, version 2.
       8             : 
       9             :    plumed is free software: you can redistribute it and/or modify
      10             :    it under the terms of the GNU Lesser General Public License as published by
      11             :    the Free Software Foundation, either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    plumed is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU Lesser General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU Lesser General Public License
      20             :    along with plumed.  If not, see <http://www.gnu.org/licenses/>.
      21             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      22             : 
      23             : #include "OpenMP.h"
      24             : #include "Tools.h"
      25             : #include <cstdlib>
      26             : #include <cstring>
      27             : #if defined(_OPENMP)
      28             : #include <omp.h>
      29             : #endif
      30             : #if defined(__linux__) && defined(_OPENMP) && defined(__PLUMED_HAS_DLOPEN) && defined(__PLUMED_HAS_DLADDR)
      31             : #include <dlfcn.h>
      32             : #endif
      33             : 
      34             : namespace PLMD {
      35             : 
      36             : namespace OpenMP {
      37             : 
      38      807846 : void retainRuntime() {
      39             : #if defined(__linux__) && defined(_OPENMP) && defined(__PLUMED_HAS_DLOPEN) && defined(__PLUMED_HAS_DLADDR) && defined(RTLD_NODELETE)
      40      807846 :   const char* retain=std::getenv("PLUMED_OPENMP_RETAIN_RUNTIME");
      41      807846 :   if(retain && std::strcmp(retain, "no")==0) {
      42             :     return;
      43             :   }
      44             :   // A kernel can be unloaded while idle OpenMP workers are still executing in
      45             :   // the runtime. Retain that runtime, rather than the kernel or its other
      46             :   // dependencies. The function-local static also serializes concurrent callers.
      47        6107 :   static const bool retained=[] {
      48        6107 :     Dl_info runtime{}, kernel{};
      49        6107 :     plumed_massert(dladdr(reinterpret_cast<void*>(&omp_get_thread_num), &runtime),
      50             :                    "Cannot locate the OpenMP runtime");
      51        6107 :     plumed_massert(dladdr(reinterpret_cast<void*>(&retainRuntime), &kernel),
      52             :                    "Cannot locate the PLUMED kernel");
      53             :     // With a statically linked OpenMP runtime, retaining this object would also
      54             :     // retain the whole kernel (or executable). Leave that case unchanged.
      55        6107 :     if(runtime.dli_fbase==kernel.dli_fbase) {
      56             :       return true;
      57             :     }
      58        6107 :     void* handle=dlopen(runtime.dli_fname, RTLD_NOW | RTLD_LOCAL | RTLD_NODELETE);
      59        6107 :     plumed_massert(handle, "Cannot retain the OpenMP runtime");
      60             :     // NODELETE persists after closing this extra reference. No per-load handle
      61             :     // is leaked, and normal dlclose() of individual kernels remains possible.
      62        6107 :     dlclose(handle);
      63        6107 :     return true;
      64      807845 :   }();
      65             :   (void)retained;
      66             : #endif
      67             : }
      68             : 
      69             : ///singleton struct to treat the openMP setting as a global variables, but with a layer of encapsulation
      70             : struct OpenMPVars {
      71             :   unsigned cacheline_size=512;
      72             :   bool cache_set=false;
      73             :   unsigned num_threads=1;
      74             :   bool nt_env_set=false;
      75             :   static OpenMPVars & get() {
      76             :     static OpenMPVars vars;
      77             :     return vars;
      78             :   }
      79             : private:
      80             :   OpenMPVars()=default;
      81             :   OpenMPVars(OpenMPVars&)=delete;
      82             :   OpenMPVars& operator=(OpenMPVars&&)=delete;
      83             : };
      84             : 
      85           4 : void setNumThreads(const unsigned nt) {
      86           4 :   OpenMPVars::get().num_threads=nt;
      87           4 : }
      88             : 
      89      918685 : unsigned getCachelineSize() {
      90      918685 :   if(!OpenMPVars::get().cache_set) {
      91        1037 :     if(std::getenv("PLUMED_CACHELINE_SIZE")) {
      92           1 :       Tools::convert(std::getenv("PLUMED_CACHELINE_SIZE"),OpenMPVars::get().cacheline_size);
      93             :     }
      94        1037 :     OpenMPVars::get().cache_set = true;
      95             :   }
      96      918685 :   return OpenMPVars::get().cacheline_size;
      97             : }
      98             : 
      99    45767925 : unsigned getNumThreads() {
     100    45767925 :   if(!OpenMPVars::get().nt_env_set) {
     101        1039 :     if(std::getenv("PLUMED_NUM_THREADS")) {
     102        1039 :       Tools::convert(std::getenv("PLUMED_NUM_THREADS"),OpenMPVars::get().num_threads);
     103             :     }
     104        1039 :     OpenMPVars::get().nt_env_set = true;
     105             :   }
     106    45767925 :   return OpenMPVars::get().num_threads;
     107             : }
     108             : 
     109    76360763 : unsigned getThreadNum() {
     110             : #if defined(_OPENMP)
     111    76360763 :   return omp_get_thread_num();
     112             : #else
     113             :   return 0;
     114             : #endif
     115             : }
     116             : 
     117             : }//namespace OpenMP
     118             : }//namespace PLMD

Generated by: LCOV version 1.16