Reference documentation for deal.II version 9.0.0
multithread_info.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2000 - 2018 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #include <deal.II/base/multithread_info.h>
17 #include <deal.II/base/utilities.h>
18 
19 #ifdef DEAL_II_HAVE_UNISTD_H
20 # include <unistd.h>
21 #endif
22 
23 #if (defined(__MACH__) && defined(__APPLE__)) || defined(__FreeBSD__)
24 # include <sys/types.h>
25 # include <sys/sysctl.h>
26 #endif
27 
28 #include <algorithm>
29 
30 #ifdef DEAL_II_WITH_THREADS
31 # include <deal.II/base/thread_management.h>
32 # include <tbb/task_scheduler_init.h>
33 #endif
34 
35 DEAL_II_NAMESPACE_OPEN
36 
37 #ifdef DEAL_II_WITH_THREADS
38 
39 /* Detecting how many processors a given machine has is something that
40  varies greatly between operating systems. For a few operating
41  systems, we have figured out how to do that below, but some others
42  are still missing. If you find a way to do this on your favorite
43  system, please let us know.
44  */
45 
46 
47 # if defined(__linux__) || defined(__sun__) || defined(__osf__) || defined(_AIX)
48 
49 unsigned int MultithreadInfo::get_n_cpus()
50 {
51  return sysconf(_SC_NPROCESSORS_ONLN);
52 }
53 
54 # elif (defined(__MACH__) && defined(__APPLE__)) || defined(__FreeBSD__)
55 // This is only tested on a dual G5 2.5GHz running MacOSX 10.3.6
56 // and on an Intel Mac Book Pro.
57 // If it doesn't work please contact the mailinglist.
58 unsigned int MultithreadInfo::get_n_cpus()
59 {
60  int mib[2];
61  int n_cpus;
62  size_t len;
63 
64  mib[0] = CTL_HW;
65  mib[1] = HW_NCPU;
66  len = sizeof(n_cpus);
67  sysctl(mib, 2, &n_cpus, &len, NULL, 0);
68 
69  return n_cpus;
70 }
71 
72 # else
73 
74 // If you get n_cpus=1 although you are on a multi-processor machine,
75 // then this may have two reasons: either because the system macros,
76 // e.g.__linux__, __sgi__, etc. weren't defined by the compiler or the
77 // detection of processors is really not implemented for your specific
78 // system. In the first case you can add e.g. -D__sgi__ to your
79 // compiling flags, in the latter case you need to implement the
80 // get_n_cpus() function for your system.
81 //
82 // In both cases, this #else case is compiled, a fact that you can
83 // easily verify by uncommenting the following #error directive,
84 // recompiling and getting a compilation error right at that line.
85 // After definition of the system macro or the implementation of the
86 // new detection this #error message during compilation shouldn't
87 // occur any more.
88 //
89 // Please send all new implementations of detection of processors to
90 // the deal.II mailing list, such that it can be included into the
91 // next deal.II release.
92 
93 //#error Detection of Processors not supported on this OS. Setting n_cpus=1 by default.
94 
96 {
97  return 1;
98 }
99 
100 # endif
101 
103 {
105 }
106 
107 
108 void MultithreadInfo::set_thread_limit(const unsigned int max_threads)
109 {
110  // set the maximal number of threads to the given value as specified
111  n_max_threads = max_threads;
112 
113  // then also see if something was given in the environment
114  {
115  const char *penv = getenv ("DEAL_II_NUM_THREADS");
116  if (penv!=nullptr)
117  {
118  unsigned int max_threads_env = numbers::invalid_unsigned_int;
119  try
120  {
121  max_threads_env = Utilities::string_to_int(std::string(penv));
122  }
123  catch (...)
124  {
125  AssertThrow (false,
126  ExcMessage (std::string("When specifying the <DEAL_II_NUM_THREADS> environment "
127  "variable, it needs to be something that can be interpreted "
128  "as an integer. The text you have in the environment "
129  "variable is <") + penv + ">"));
130  }
131 
132  AssertThrow (max_threads_env>0,
133  ExcMessage ("When specifying the <DEAL_II_NUM_THREADS> environment "
134  "variable, it needs to be a positive number."));
135 
137  n_max_threads = std::min(n_max_threads, max_threads_env);
138  else
139  n_max_threads = max_threads_env;
140  }
141  }
142  // Without restrictions from the user query TBB for the recommended number
143  // of threads:
145  n_max_threads = tbb::task_scheduler_init::default_num_threads();
146 
147  // Initialize the scheduler and destroy the old one before doing so
148  static tbb::task_scheduler_init dummy (tbb::task_scheduler_init::deferred);
149  if (dummy.is_active())
150  dummy.terminate();
151  dummy.initialize(n_max_threads);
152 }
153 
154 
156 {
158  return n_max_threads;
159 }
160 
161 
162 #else // not in MT mode
163 
164 unsigned int MultithreadInfo::get_n_cpus()
165 {
166  return 1;
167 }
168 
169 unsigned int MultithreadInfo::n_cores()
170 {
171  return 1;
172 }
173 
174 unsigned int MultithreadInfo::n_threads()
175 {
176  return 1;
177 }
178 
179 void MultithreadInfo::set_thread_limit(const unsigned int)
180 {
181 }
182 
183 #endif
184 
185 
187 {
188  return n_threads() == 1;
189 }
190 
191 
192 std::size_t
194 {
195  // only simple data elements, so
196  // use sizeof operator
197  return sizeof (MultithreadInfo);
198 }
199 
200 
201 void
203 {
204  static bool done = false;
205  if (done)
206  return;
207 
209  done = true;
210 }
211 
212 
213 
216 
217 namespace
218 {
219 // Force the first call to set_thread_limit happen before any tasks in TBB are
220 // used. This is necessary as tbb::task_scheduler_init has no effect if TBB
221 // got automatically initialized (which happens the first time we use it).
222  struct DoOnce
223  {
224  DoOnce ()
225  {
227  }
228  } do_once;
229 }
230 
231 DEAL_II_NAMESPACE_CLOSE
static const unsigned int invalid_unsigned_int
Definition: types.h:173
static const unsigned int n_cpus
MultithreadInfo()=delete
static unsigned int n_cores()
#define AssertThrow(cond, exc)
Definition: exceptions.h:1221
static ::ExceptionBase & ExcMessage(std::string arg1)
#define Assert(cond, exc)
Definition: exceptions.h:1142
static void initialize_multithreading()
static bool is_running_single_threaded()
static unsigned int n_max_threads
static std::size_t memory_consumption()
static void set_thread_limit(const unsigned int max_threads=numbers::invalid_unsigned_int)
int string_to_int(const std::string &s)
Definition: utilities.cc:207
static unsigned int n_threads()
static ::ExceptionBase & ExcInternalError()
static unsigned int get_n_cpus()