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