Tpetra parallel linear algebra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Tpetra_Details_Behavior.cpp
1 /*
2 // @HEADER
3 // ***********************************************************************
4 //
5 // Tpetra: Templated Linear Algebra Services Package
6 // Copyright (2008) Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // ************************************************************************
39 // @HEADER
40 */
42 #include "TpetraCore_config.h"
43 #include <algorithm> // std::transform
44 #include <cstdlib> // std::getenv
45 #include <cctype> // std::toupper
46 #include <string>
47 #include <map>
48 #include <vector>
49 #include <functional>
50 #include "Teuchos_TestForException.hpp"
51 #include "Teuchos_OrdinalTraits.hpp"
52 #include <stdexcept>
53 
54 namespace Tpetra {
55 namespace Details {
56 
57 namespace BehaviorDetails {
58 std::map<std::string, std::map<std::string, bool> > namedVariableMap_;
59 bool verboseDisabled_ = false;
60 bool timingDisabled_ = false;
61 }
62 
63 namespace { // (anonymous)
64 
65  enum EnvironmentVariableState
66  {
67  EnvironmentVariableIsSet_ON,
68  EnvironmentVariableIsSet_OFF,
69  EnvironmentVariableIsSet,
70  EnvironmentVariableIsNotSet
71  };
72 
73  // See example here:
74  //
75  // http://en.cppreference.com/w/cpp/string/byte/toupper
76  std::string stringToUpper (std::string s)
77  {
78  std::transform (s.begin (), s.end (), s.begin (),
79  [] (unsigned char c) { return std::toupper (c); });
80  return s;
81  }
82 
83  void
84  split(const std::string& s,
85  std::function<void(const std::string&)> f,
86  const char sep=',')
87  {
88  typedef std::string::size_type size_type;
89  size_type cur_pos, last_pos=0, length=s.length();
90  while(last_pos < length + 1)
91  {
92  cur_pos = s.find_first_of(sep, last_pos);
93  if(cur_pos == std::string::npos)
94  {
95  cur_pos = length;
96  }
97  if(cur_pos!=last_pos) {
98  auto token = std::string(s.data()+last_pos, (size_type)cur_pos-last_pos);
99  f(token);
100  }
101  last_pos = cur_pos + 1;
102  }
103  return;
104  }
105 
106  EnvironmentVariableState
107  environmentVariableState(const std::string& environmentVariableValue)
108  {
109  std::string v = stringToUpper(environmentVariableValue);
110  if (v == "1" || v == "YES" || v == "TRUE" || v == "ON")
111  // Environment variable is "ON"
112  return EnvironmentVariableIsSet_ON;
113  else if (v == "0" || v == "NO" || v == "FALSE" || v == "OFF")
114  // Environment variable is "OFF"
115  return EnvironmentVariableIsSet_OFF;
116  // Environment has some other non-boolean value
117  return EnvironmentVariableIsSet;
118  }
119 
120  void
121  setEnvironmentVariableMap (const char environmentVariableName[],
122  std::map<std::string,std::map<std::string, bool> >& valsMap,
123  const bool defaultValue)
124  {
125  using std::map;
126  using std::getenv;
127  using std::string;
128  using std::vector;
129 
130  // Set the default value for this variable
131  valsMap[environmentVariableName] = map<string,bool>{{"DEFAULT", defaultValue}};
132 
133  const char* varVal = getenv (environmentVariableName);
134  if (varVal == nullptr) {
135  // Environment variable is not set, use the default value for any named
136  // variants
137  return;
138  }
139 
140  // Variable is not empty.
141  const string varStr(varVal);
142  vector<string> names;
143  split(varStr, [&](const string& x){names.push_back(x);});
144  for (auto const& name: names) {
145  auto state = environmentVariableState(name);
146  if (state == EnvironmentVariableIsSet_ON) {
147  // Environment variable was set as ENVAR_NAME=[1,YES,TRUE,ON]
148  // Global value takes precedence
149  valsMap[environmentVariableName]["DEFAULT"] = true;
150  }
151  else if (state == EnvironmentVariableIsSet_OFF) {
152  // Environment variable was set as ENVAR_NAME=[0,NO,FALSE,OFF]
153  // Global value takes precedence
154  valsMap[environmentVariableName]["DEFAULT"] = false;
155  }
156  else {
157  // Environment variable was set as ENVAR_NAME=...:name:...
158  // So we set the mapping true for this named variant
159  valsMap[environmentVariableName][name] = true;
160  }
161  }
162  return;
163  }
164 
165  bool
166  getEnvironmentVariableAsBool (const char environmentVariableName[],
167  const bool defaultValue)
168  {
169  const char* varVal = std::getenv (environmentVariableName);
170 
171  bool retVal = defaultValue;
172  if (varVal != nullptr) {
173  auto state = environmentVariableState(std::string(varVal));
174  if (state == EnvironmentVariableIsSet_ON) retVal = true;
175  else if (state == EnvironmentVariableIsSet_OFF) retVal = false;
176  }
177  return retVal;
178  }
179 
180  size_t
181  getEnvironmentVariableAsSize(const char environmentVariableName[],
182  const size_t defaultValue)
183  {
184  const char prefix[] = "Tpetra::Details::Behavior: ";
185 
186  const char* varVal = std::getenv(environmentVariableName);
187  if (varVal == nullptr) {
188  return defaultValue;
189  }
190  else {
191  // This could throw invalid_argument or out_of_range.
192  // Go ahead and let it do so.
193  long long val = std::stoll(stringToUpper(varVal));
194  if (val < static_cast<long long>(0)) {
195  // If negative - user has requested threshold be lifted
196  return std::numeric_limits<size_t>::max();
197  }
198 // TEUCHOS_TEST_FOR_EXCEPTION
199 // (val < static_cast<long long>(0), std::out_of_range,
200 // prefix << "Environment variable \""
201 // << environmentVariableName << "\" is supposed to be a size, "
202 // "but it has a negative integer value " << val << ".");
203  if (sizeof(long long) > sizeof(size_t)) {
204  // It's hard to test this code, but I want to try writing it
205  // at least, in case we ever have to run on 32-bit machines or
206  // machines with sizeof(long long)=16 and sizeof(size_t)=8.
207  constexpr long long maxSizeT =
208  static_cast<long long>(std::numeric_limits<size_t>::max());
209  TEUCHOS_TEST_FOR_EXCEPTION
210  (val > maxSizeT, std::out_of_range, prefix << "Environment "
211  "variable \"" << environmentVariableName << "\" has a "
212  "value " << val << " larger than the largest size_t value "
213  << maxSizeT << ".");
214  }
215  return static_cast<size_t>(val);
216  }
217  }
218 
219  bool
220  idempotentlyGetEnvironmentVariableAsBool (bool& value,
221  bool& initialized,
222  const char environmentVariableName[],
223  const bool defaultValue)
224  {
225  if (! initialized) {
226  value = getEnvironmentVariableAsBool (environmentVariableName,
227  defaultValue);
228  initialized = true;
229  }
230  return value;
231  }
232 
233  bool
234  idempotentlyGetNamedEnvironmentVariableAsBool (const char name[],
235  bool& initialized,
236  const char environmentVariableName[],
237  const bool defaultValue)
238  {
239  using BehaviorDetails::namedVariableMap_;
240  if (! initialized) {
241  setEnvironmentVariableMap (environmentVariableName,
242  namedVariableMap_,
243  defaultValue);
244  initialized = true;
245  }
246  auto thisEnvironmentVariableMap = namedVariableMap_[environmentVariableName];
247  auto thisEnvironmentVariable = thisEnvironmentVariableMap.find(name);
248  if (thisEnvironmentVariable != thisEnvironmentVariableMap.end())
249  return thisEnvironmentVariable->second;
250  return thisEnvironmentVariableMap["DEFAULT"];
251  }
252 
253  size_t
254  idempotentlyGetEnvironmentVariableAsSize
255  (size_t& value,
256  bool& initialized,
257  const char environmentVariableName[],
258  const size_t defaultValue)
259  {
260  if (! initialized) {
261  value = getEnvironmentVariableAsSize(environmentVariableName,
262  defaultValue);
263  initialized = true;
264  }
265  return value;
266  }
267 
268  constexpr bool debugDefault () {
269 #ifdef HAVE_TPETRA_DEBUG
270  return true;
271 #else
272  return false;
273 #endif // HAVE_TPETRA_DEBUG
274  }
275 
276  constexpr bool verboseDefault () {
277  return false;
278  }
279 
280  constexpr bool timingDefault () {
281  return false;
282  }
283 
284  constexpr bool assumeMpiIsCudaAwareDefault () {
285 #ifdef TPETRA_ASSUME_CUDA_AWARE_MPI
286  return true;
287 #else
288  return false;
289 #endif // TPETRA_ASSUME_CUDA_AWARE_MPI
290  }
291 
292  constexpr bool hierarchicalUnpackDefault () {
293  return true;
294  }
295 
296 } // namespace (anonymous)
297 
299 {
300  constexpr char envVarName[] = "TPETRA_DEBUG";
301  constexpr bool defaultValue = debugDefault ();
302 
303  static bool value_ = defaultValue;
304  static bool initialized_ = false;
305  return idempotentlyGetEnvironmentVariableAsBool (value_,
306  initialized_,
307  envVarName,
308  defaultValue);
309 }
310 
312 {
313  if (BehaviorDetails::verboseDisabled_) return false;
314 
315  constexpr char envVarName[] = "TPETRA_VERBOSE";
316  constexpr bool defaultValue = verboseDefault ();
317 
318  static bool value_ = defaultValue;
319  static bool initialized_ = false;
320  return idempotentlyGetEnvironmentVariableAsBool (value_,
321  initialized_,
322  envVarName,
323  defaultValue);
324 }
325 
327 {
328  if (BehaviorDetails::timingDisabled_) return false;
329 
330  constexpr char envVarName[] = "TPETRA_TIMING";
331  constexpr bool defaultValue = timingDefault ();
332 
333  static bool value_ = defaultValue;
334  static bool initialized_ = false;
335  return idempotentlyGetEnvironmentVariableAsBool (value_,
336  initialized_,
337  envVarName,
338  defaultValue);
339 }
340 
342 {
343  constexpr char envVarName[] = "TPETRA_ASSUME_CUDA_AWARE_MPI";
344  constexpr bool defaultValue = assumeMpiIsCudaAwareDefault ();
345 
346  static bool value_ = defaultValue;
347  static bool initialized_ = false;
348  return idempotentlyGetEnvironmentVariableAsBool (value_,
349  initialized_,
350  envVarName,
351  defaultValue);
352 }
353 
355 {
356  // only call getenv once, save the value.
357  static int savedval=-1;
358  if(savedval!=-1) return savedval;
359  const char* varVal = std::getenv ("MM_TAFC_OptimizationCoreCount");
360  if (varVal == nullptr) {
361  savedval = 3000;
362  return savedval;
363  }
364  savedval = std::stoi(std::string(varVal));
365  return savedval;
366 }
367 
369 {
370  constexpr char envVarName[] = "TPETRA_VERBOSE_PRINT_COUNT_THRESHOLD";
371  constexpr size_t defaultValue (200);
372 
373  static size_t value_ = defaultValue;
374  static bool initialized_ = false;
375  return idempotentlyGetEnvironmentVariableAsSize
376  (value_, initialized_, envVarName, defaultValue);
377 }
378 
380 {
381  constexpr char envVarName[] = "TPETRA_ROW_IMBALANCE_THRESHOLD";
382  constexpr size_t defaultValue (256);
383 
384  static size_t value_ = defaultValue;
385  static bool initialized_ = false;
386  return idempotentlyGetEnvironmentVariableAsSize
387  (value_, initialized_, envVarName, defaultValue);
388 }
389 
391 {
392  constexpr char envVarName[] = "TPETRA_MULTIVECTOR_USE_MERGE_PATH";
393  constexpr bool defaultValue = false;
394 
395  static bool value_ = defaultValue;
396  static bool initialized_ = false;
397  return idempotentlyGetEnvironmentVariableAsBool
398  (value_, initialized_, envVarName, defaultValue);
399 }
400 
402 {
403  constexpr char envVarName[] = "TPETRA_VECTOR_DEVICE_THRESHOLD";
404  constexpr size_t defaultValue (10000);
405 
406  static size_t value_ = defaultValue;
407  static bool initialized_ = false;
408  return idempotentlyGetEnvironmentVariableAsSize
409  (value_, initialized_, envVarName, defaultValue);
410 }
411 
413 {
414  constexpr char envVarName[] = "TPETRA_HIERARCHICAL_UNPACK_BATCH_SIZE";
415 
416 #ifdef HAVE_TPETRA_INST_CUDA
417  constexpr size_t defaultValue (16);
418 #else
419  constexpr size_t defaultValue (256);
420 #endif
421 
422  static size_t value_ = defaultValue;
423  static bool initialized_ = false;
424  return idempotentlyGetEnvironmentVariableAsSize
425  (value_, initialized_, envVarName, defaultValue);
426 }
427 
429 {
430  constexpr char envVarName[] = "TPETRA_HIERARCHICAL_UNPACK_TEAM_SIZE";
431 #ifdef HAVE_TPETRA_INST_CUDA
432  const size_t defaultValue (16);
433 #else
434  const size_t defaultValue (Teuchos::OrdinalTraits<size_t>::invalid ());
435 #endif
436 
437  static size_t value_ = defaultValue;
438  static bool initialized_ = false;
439  return idempotentlyGetEnvironmentVariableAsSize
440  (value_, initialized_, envVarName, defaultValue);
441 }
442 
444 {
445  constexpr char envVarName[] = "TPETRA_USE_TEUCHOS_TIMERS";
446  constexpr bool defaultValue(false);
447 
448  static bool value_ = defaultValue;
449  static bool initialized_ = false;
450  return idempotentlyGetEnvironmentVariableAsBool
451  (value_, initialized_, envVarName, defaultValue);
452 }
453 
455 {
456  constexpr char envVarName[] = "TPETRA_USE_KOKKOS_PROFILING";
457  constexpr bool defaultValue(false);
458 
459  static bool value_ = defaultValue;
460  static bool initialized_ = false;
461  return idempotentlyGetEnvironmentVariableAsBool
462  (value_, initialized_, envVarName, defaultValue);
463 }
464 
465 
466 bool Behavior::debug (const char name[])
467 {
468  constexpr char envVarName[] = "TPETRA_DEBUG";
469  constexpr bool defaultValue = false;
470 
471  static bool initialized_ = false;
472  return idempotentlyGetNamedEnvironmentVariableAsBool (name,
473  initialized_,
474  envVarName,
475  defaultValue);
476 }
477 
478 bool Behavior::verbose (const char name[])
479 {
480  if (BehaviorDetails::verboseDisabled_) return false;
481 
482  constexpr char envVarName[] = "TPETRA_VERBOSE";
483  constexpr bool defaultValue = false;
484 
485  static bool initialized_ = false;
486  return idempotentlyGetNamedEnvironmentVariableAsBool (name,
487  initialized_,
488  envVarName,
489  defaultValue);
490 }
491 
493  BehaviorDetails::verboseDisabled_ = false;
494 }
495 
497  BehaviorDetails::verboseDisabled_ = true;
498 }
499 
500 bool Behavior::timing (const char name[])
501 {
502  if (BehaviorDetails::timingDisabled_) return false;
503 
504  constexpr char envVarName[] = "TPETRA_TIMING";
505  constexpr bool defaultValue = false;
506 
507  static bool initialized_ = false;
508  return idempotentlyGetNamedEnvironmentVariableAsBool (name,
509  initialized_,
510  envVarName,
511  defaultValue);
512 }
513 
515  BehaviorDetails::timingDisabled_ = false;
516 }
517 
519  BehaviorDetails::timingDisabled_ = true;
520 }
521 
523 {
524  constexpr char envVarName[] = "TPETRA_HIERARCHICAL_UNPACK";
525  constexpr bool defaultValue = hierarchicalUnpackDefault();
526 
527  static bool value_ = defaultValue;
528  static bool initialized_ = false;
529  return idempotentlyGetEnvironmentVariableAsBool (value_,
530  initialized_,
531  envVarName,
532  defaultValue);
533 }
534 
535 } // namespace Details
536 } // namespace Tpetra
537 
static bool useMergePathMultiVector()
Whether to use the cuSPARSE merge path algorithm to perform sparse matrix-multivector products...
static int TAFC_OptimizationCoreCount()
MPI process count above which Tpetra::CrsMatrix::transferAndFillComplete will attempt to do advanced ...
static bool timing()
Whether Tpetra is in timing mode.
static void disable_verbose_behavior()
Disable verbose mode, programatically.
static size_t multivectorKernelLocationThreshold()
the threshold for transitioning from device to host
static bool debug()
Whether Tpetra is in debug mode.
static size_t hierarchicalUnpackTeamSize()
Size of team for hierarchical unpacking.
static bool profilingRegionUseTeuchosTimers()
Use Teuchos::Timer in Tpetra::ProfilingRegion.
static void disable_timing()
Disable timing, programatically.
static bool hierarchicalUnpack()
Unpack rows of a matrix using hierarchical unpacking.
static bool assumeMpiIsCudaAware()
Whether to assume that MPI is CUDA aware.
static void enable_timing()
Enable timing, programatically.
static bool verbose()
Whether Tpetra is in verbose mode.
static size_t rowImbalanceThreshold()
Threshold for deciding if a local matrix is &quot;imbalanced&quot; in the number of entries per row...
void transform(const char kernelLabel[], ExecutionSpace execSpace, GlobalDataStructure &input, GlobalDataStructure &output, UnaryFunctionType f)
For each local entry input_i of input, assign f(input_i) to the corresponding local entry output_i of...
static size_t hierarchicalUnpackBatchSize()
Size of batch for hierarchical unpacking.
static void enable_verbose_behavior()
Enable verbose mode, programatically.
static size_t verbosePrintCountThreshold()
Number of entries below which arrays, lists, etc. will be printed in debug mode.
static bool profilingRegionUseKokkosProfiling()
Use Kokkos::Profiling in Tpetra::ProfilingRegion.
Declaration of Tpetra::Details::Behavior, a class that describes Tpetra&#39;s behavior.