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 assumeMpiIsGPUAwareDefault () {
285 #ifdef TPETRA_ASSUME_GPU_AWARE_MPI
286  return true;
287 #else
288  return false;
289 #endif // TPETRA_ASSUME_GPU_AWARE_MPI
290  }
291 
292  constexpr bool cudaLaunchBlockingDefault () {
293  return false;
294  }
295 
296  constexpr bool hierarchicalUnpackDefault () {
297  return true;
298  }
299 
300 } // namespace (anonymous)
301 
303 {
304  constexpr char envVarName[] = "TPETRA_DEBUG";
305  constexpr bool defaultValue = debugDefault ();
306 
307  static bool value_ = defaultValue;
308  static bool initialized_ = false;
309  return idempotentlyGetEnvironmentVariableAsBool (value_,
310  initialized_,
311  envVarName,
312  defaultValue);
313 }
314 
316 {
317  if (BehaviorDetails::verboseDisabled_) return false;
318 
319  constexpr char envVarName[] = "TPETRA_VERBOSE";
320  constexpr bool defaultValue = verboseDefault ();
321 
322  static bool value_ = defaultValue;
323  static bool initialized_ = false;
324  return idempotentlyGetEnvironmentVariableAsBool (value_,
325  initialized_,
326  envVarName,
327  defaultValue);
328 }
329 
331 {
332  if (BehaviorDetails::timingDisabled_) return false;
333 
334  constexpr char envVarName[] = "TPETRA_TIMING";
335  constexpr bool defaultValue = timingDefault ();
336 
337  static bool value_ = defaultValue;
338  static bool initialized_ = false;
339  return idempotentlyGetEnvironmentVariableAsBool (value_,
340  initialized_,
341  envVarName,
342  defaultValue);
343 }
344 
346 {
347  constexpr char envVarName[] = "TPETRA_ASSUME_GPU_AWARE_MPI";
348  constexpr bool defaultValue = assumeMpiIsGPUAwareDefault ();
349 
350  static bool value_ = defaultValue;
351  static bool initialized_ = false;
352  return idempotentlyGetEnvironmentVariableAsBool (value_,
353  initialized_,
354  envVarName,
355  defaultValue);
356 }
357 
359 {
360  constexpr char envVarName[] = "CUDA_LAUNCH_BLOCKING";
361  constexpr bool defaultValue = cudaLaunchBlockingDefault ();
362 
363  static bool value_ = defaultValue;
364  static bool initialized_ = false;
365  return idempotentlyGetEnvironmentVariableAsBool (value_,
366  initialized_,
367  envVarName,
368  defaultValue);
369 }
370 
372 {
373  // only call getenv once, save the value.
374  static int savedval=-1;
375  if(savedval!=-1) return savedval;
376  const char* varVal = std::getenv ("MM_TAFC_OptimizationCoreCount");
377  if (varVal == nullptr) {
378  savedval = 3000;
379  return savedval;
380  }
381  savedval = std::stoi(std::string(varVal));
382  return savedval;
383 }
384 
386 {
387  constexpr char envVarName[] = "TPETRA_VERBOSE_PRINT_COUNT_THRESHOLD";
388  constexpr size_t defaultValue (200);
389 
390  static size_t value_ = defaultValue;
391  static bool initialized_ = false;
392  return idempotentlyGetEnvironmentVariableAsSize
393  (value_, initialized_, envVarName, defaultValue);
394 }
395 
397 {
398  constexpr char envVarName[] = "TPETRA_ROW_IMBALANCE_THRESHOLD";
399  constexpr size_t defaultValue (256);
400 
401  static size_t value_ = defaultValue;
402  static bool initialized_ = false;
403  return idempotentlyGetEnvironmentVariableAsSize
404  (value_, initialized_, envVarName, defaultValue);
405 }
406 
408 {
409  constexpr char envVarName[] = "TPETRA_MULTIVECTOR_USE_MERGE_PATH";
410  constexpr bool defaultValue = false;
411 
412  static bool value_ = defaultValue;
413  static bool initialized_ = false;
414  return idempotentlyGetEnvironmentVariableAsBool
415  (value_, initialized_, envVarName, defaultValue);
416 }
417 
419 {
420  constexpr char envVarName[] = "TPETRA_VECTOR_DEVICE_THRESHOLD";
421  constexpr size_t defaultValue (22000);
422 
423  static size_t value_ = defaultValue;
424  static bool initialized_ = false;
425  return idempotentlyGetEnvironmentVariableAsSize
426  (value_, initialized_, envVarName, defaultValue);
427 }
428 
430 {
431  constexpr char envVarName[] = "TPETRA_HIERARCHICAL_UNPACK_BATCH_SIZE";
432 
433 #ifdef HAVE_TPETRA_INST_CUDA
434  constexpr size_t defaultValue (16);
435 #else
436  constexpr size_t defaultValue (256);
437 #endif
438 
439  static size_t value_ = defaultValue;
440  static bool initialized_ = false;
441  return idempotentlyGetEnvironmentVariableAsSize
442  (value_, initialized_, envVarName, defaultValue);
443 }
444 
446 {
447  constexpr char envVarName[] = "TPETRA_HIERARCHICAL_UNPACK_TEAM_SIZE";
448 #ifdef HAVE_TPETRA_INST_CUDA
449  const size_t defaultValue (16);
450 #else
451  const size_t defaultValue (Teuchos::OrdinalTraits<size_t>::invalid ());
452 #endif
453 
454  static size_t value_ = defaultValue;
455  static bool initialized_ = false;
456  return idempotentlyGetEnvironmentVariableAsSize
457  (value_, initialized_, envVarName, defaultValue);
458 }
459 
461 {
462  constexpr char envVarName[] = "TPETRA_USE_TEUCHOS_TIMERS";
463  constexpr bool defaultValue(false);
464 
465  static bool value_ = defaultValue;
466  static bool initialized_ = false;
467  return idempotentlyGetEnvironmentVariableAsBool
468  (value_, initialized_, envVarName, defaultValue);
469 }
470 
472 {
473  constexpr char envVarName[] = "TPETRA_USE_KOKKOS_PROFILING";
474  constexpr bool defaultValue(false);
475 
476  static bool value_ = defaultValue;
477  static bool initialized_ = false;
478  return idempotentlyGetEnvironmentVariableAsBool
479  (value_, initialized_, envVarName, defaultValue);
480 }
481 
482 
483 bool Behavior::debug (const char name[])
484 {
485  constexpr char envVarName[] = "TPETRA_DEBUG";
486  constexpr bool defaultValue = false;
487 
488  static bool initialized_ = false;
489  return idempotentlyGetNamedEnvironmentVariableAsBool (name,
490  initialized_,
491  envVarName,
492  defaultValue);
493 }
494 
495 bool Behavior::verbose (const char name[])
496 {
497  if (BehaviorDetails::verboseDisabled_) return false;
498 
499  constexpr char envVarName[] = "TPETRA_VERBOSE";
500  constexpr bool defaultValue = false;
501 
502  static bool initialized_ = false;
503  return idempotentlyGetNamedEnvironmentVariableAsBool (name,
504  initialized_,
505  envVarName,
506  defaultValue);
507 }
508 
510  BehaviorDetails::verboseDisabled_ = false;
511 }
512 
514  BehaviorDetails::verboseDisabled_ = true;
515 }
516 
517 bool Behavior::timing (const char name[])
518 {
519  if (BehaviorDetails::timingDisabled_) return false;
520 
521  constexpr char envVarName[] = "TPETRA_TIMING";
522  constexpr bool defaultValue = false;
523 
524  static bool initialized_ = false;
525  return idempotentlyGetNamedEnvironmentVariableAsBool (name,
526  initialized_,
527  envVarName,
528  defaultValue);
529 }
530 
532  BehaviorDetails::timingDisabled_ = false;
533 }
534 
536  BehaviorDetails::timingDisabled_ = true;
537 }
538 
540 {
541  constexpr char envVarName[] = "TPETRA_HIERARCHICAL_UNPACK";
542  constexpr bool defaultValue = hierarchicalUnpackDefault();
543 
544  static bool value_ = defaultValue;
545  static bool initialized_ = false;
546  return idempotentlyGetEnvironmentVariableAsBool (value_,
547  initialized_,
548  envVarName,
549  defaultValue);
550 }
551 
553 {
554  constexpr char envVarName[] = "TPETRA_SKIP_COPY_AND_PERMUTE";
555  constexpr bool defaultValue(false);
556 
557  static bool value_ = defaultValue;
558  static bool initialized_ = false;
559  return idempotentlyGetEnvironmentVariableAsBool
560  (value_, initialized_, envVarName, defaultValue);
561 }
562 
564 {
565  constexpr char envVarName[] = "TPETRA_OVERLAP";
566  constexpr bool defaultValue(false);
567 
568  static bool value_ = defaultValue;
569  static bool initialized_ = false;
570  return idempotentlyGetEnvironmentVariableAsBool
571  (value_, initialized_, envVarName, defaultValue);
572 }
573 
574 
575 } // namespace Details
576 } // namespace Tpetra
577 
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 overlapCommunicationAndComputation()
Overlap communication and computation.
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 assumeMpiIsGPUAware()
Whether to assume that MPI is CUDA aware.
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 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...
static size_t hierarchicalUnpackBatchSize()
Size of batch for hierarchical unpacking.
static bool skipCopyAndPermuteIfPossible()
Skip copyAndPermute if possible.
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 cudaLaunchBlocking()
Whether the CUDA_LAUNCH_BLOCKING environment variable has been set.
static bool profilingRegionUseKokkosProfiling()
Use Kokkos::Profiling in Tpetra::ProfilingRegion.
Declaration of Tpetra::Details::Behavior, a class that describes Tpetra&#39;s behavior.