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 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_CUDA_AWARE_MPI";
348  constexpr bool defaultValue = assumeMpiIsCudaAwareDefault ();
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 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...
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.