Tpetra parallel linear algebra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Tpetra_Details_Random_def.hpp
1 // @HEADER
2 // *****************************************************************************
3 // Tpetra: Templated Linear Algebra Services Package
4 //
5 // Copyright 2008 NTESS and the Tpetra contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef TPETRA_DETAILS_RANDOM_DEF_HPP
11 #define TPETRA_DETAILS_RANDOM_DEF_HPP
12 
13 #include "Tpetra_Details_Random_decl.hpp"
14 #include "Teuchos_TestForException.hpp"
15 #include "Kokkos_Random.hpp"
16 
17 namespace Tpetra {
18 namespace Details {
19 
20 namespace { // anonymous
21 template <class ExecutionSpace>
22 void finalize_pool() {
23  using PoolClass = Static_Random_XorShift64_Pool<ExecutionSpace>;
24  if (PoolClass::pool_ != nullptr) {
25  delete PoolClass::pool_;
26  }
27  PoolClass::pool_ = nullptr;
28 }
29 } // end namespace
30 
31 template <class ExecutionSpace>
32 unsigned int Static_Random_XorShift64_Pool<ExecutionSpace>::getSeedFromRank(int mpi_rank) {
33  // Seed the pseudorandom number generator using the calling
34  // process' rank. This helps decorrelate different process'
35  // pseudorandom streams. It's not perfect but it's effective and
36  // doesn't require MPI communication. The seed also includes bits
37  // from the standard library's rand().
38  uint64_t myRank = static_cast<uint64_t>(mpi_rank);
39  uint64_t seed64 = static_cast<uint64_t>(std::rand()) + myRank + 17311uLL;
40  unsigned int seed = static_cast<unsigned int>(seed64 & 0xffffffff);
41  return seed;
42 }
43 
44 template <class ExecutionSpace>
45 void Static_Random_XorShift64_Pool<ExecutionSpace>::
46  resetPool(int mpi_rank) {
47  if (isSet())
48  delete pool_;
49  else
50  Kokkos::push_finalize_hook(finalize_pool<ExecutionSpace>);
51 
52  pool_ = new Kokkos::Random_XorShift64_Pool<ExecutionSpace>(getSeedFromRank(mpi_rank));
53 }
54 
55 template <class ExecutionSpace>
56 bool Static_Random_XorShift64_Pool<ExecutionSpace>::
57  isSet() {
58  return pool_ != nullptr;
59 }
60 
61 template <class ExecutionSpace>
62 Kokkos::Random_XorShift64_Pool<ExecutionSpace>& Static_Random_XorShift64_Pool<ExecutionSpace>::
63  getPool() {
64  TEUCHOS_TEST_FOR_EXCEPTION(!isSet(), std::runtime_error, "Tpetra::Details::Static_Random_XorShift64_Pool: resetPool() must be called before getPool");
65  return *pool_;
66 }
67 
68 } // namespace Details
69 } // namespace Tpetra
70 
71 //
72 // Explicit instantiation macro
73 //
74 // Must be expanded from within the Tpetra namespace!
75 // NOTE: Tpetra::Details::Random is templated on execution space,
76 // but we can use this trick to get it out of the node.
77 //
78 
79 #define TPETRA_DETAILS_RANDOM_INSTANT(NODE) \
80  template <> \
81  Kokkos::Random_XorShift64_Pool<typename NODE::execution_space>* Details::Static_Random_XorShift64_Pool<typename NODE::execution_space>::pool_ = nullptr; \
82  template class Details::Static_Random_XorShift64_Pool<typename NODE::execution_space>;
83 
84 #endif // TPETRA_DETAILS_RANDOM_DEF_HPP